caioj1063·動態規劃入門(一維一邊推1:美元和馬克)
1063:動態規劃入門(一維一邊推1:美元和馬克)
時間限制: 1 Sec 記憶體限制: 128 MB
題目描述
【問題描述】
今天6:00起床,我轉身發現枕頭邊有100美元。
出門的時候發現門口有家冰淇淋店,拉了很長的橫幅:“今天100美元和400馬克互換”
第二天的橫幅是:“今天100美元和300馬克互換”
第三天的橫幅是:“今天100美元和500馬克互換”
第四天的橫幅是:“今天100美元和300馬克互換”
第五天的橫幅是:“今天100美元和250馬克互換”
第五天的晚上,我靈光一閃,決定坐時光飛機回到第一天的上午6:00,準備發大財!
我是這麼做的:
Day 1 … 用 100.0000 美元 換 400.0000 馬克
晚上我手裡拿著400.0000馬克安心睡覺了
Day 2 … 用 400.0000 馬克 換 133.3333 美元
晚上我手裡拿著133.3333美元安心睡覺了
Day 3 … 用 133.3333 美元 換 666.6666 馬克
晚上我手裡拿著666.6666馬克安心睡覺了
Day 4 … 我手裡拿著666.6666 馬克 不換美元,因為我知道明天換更好呀
晚上我手裡拿著666.6666馬克安心睡覺了
Day 5 … 用 666.6666 馬克 換 266.6666 美元
晚上我手裡拿著266.6666美元偷笑,我賺了166.6666美元。厲害吧?你有時光機嗎?
第六天全世界都不使用馬克了,所以最後一天留在手裡的必須是美元!
【輸入檔案】
第一行是一個自然數N,1≤N≤100,表示天數。
接下來的N行中每行是一個自然數a[i],1≤a[i]≤1000。
表示預先知道的第i天100美元 和 A馬克 能互換。
【輸出檔案】
一行,即最後一天晚上手裡的美元數目(保留兩位小數)。
輸入
輸出
樣例輸入
5
400
300
500
300
250
樣例輸出
266.67
提示
感受隱形路徑
題外話
斷更良久。。。
雖然說都是簡單題
刷水題是會長自信2333
六校聯考考完,,,物理生物藥丸,暑假沒看qwq
可愛的題解
動態規劃的基本題
mymax函式比較最大值
用double是因為資料處理中會有小數出現所以一律用double
{
d[i]=mymax(d[i-1],m[i-1]*100.0/a[i]);
m[i]=mymax(m[i-1],d[i-1]*a[i]/100.0);
}
這一步便是此程式碼的核心,d表示美元的最佳選擇,m為馬克的最佳選擇,d[i]更新為不換mark繼承上一天或者更換mark,或者換mark,下一天又會用到剛剛更新的資料一直到最後。
m同理。一直做到最後一題輸出dn即可
其中一條隱藏的路徑
為什麼這樣做的能正解呢
這便是動態規劃適用的性質之一
無後效性與最優子結構性
通俗易懂的說法
無後效性:後面發生的事件對已發生過的沒有影響
最優子結構性:最優解一定包含子問題的最優解
*在本題中新一天是否決定換並不會對過去造成影響
*最終的最優解都取決於前一天的最優解
*故可用動態規劃演算法(Dynamic Programming)
這是一個開端,相信大家已經都清楚啦>_
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
double mymax(double x,double y){
return x>y?x:y;
}
int main(){
double a[110],d[110],m[110];
int n;
scanf("%d",&n);
scanf("%lf",&a[1]);
d[1]=100.0;m[1]=a[1];
for (int i=2;i<=n;i++){
scanf("%lf",&a[i]);
d[i]=mymax(d[i-1],m[i-1]*100.0/a[i]);
m[i]=mymax(m[i-1],d[i-1]*a[i]/100.0);
}
printf("%0.2lf\n",d[n]);
return 0;
}