1. 程式人生 > >1-10假期訓練(hdu-2059 簡單dp)

1-10假期訓練(hdu-2059 簡單dp)

題目一:傳送門

思路:水題,模擬即可

題目二:傳送門

思路:dp,決策每個充電站是否要充電。(決策只有搜尋,DP兩種解決方法)

(1)考慮狀態的個數,n+2個,因為除了n個還有位置0,終點len兩種狀態;

前一個狀態可以推出後一個狀態,所以可以得到迴圈的順序外迴圈1--n,內迴圈i-1--0。

(2)狀態轉移方程:dp[i]=MIN(dp[i],dp[i]+x,dp[i]+y),x表示要充電,y表示不要充電。

(3)考慮x和y的求法:

如果j==0,只考慮x即可,因為第一次肯定充滿電

如果j!=0,考慮x,y分為dis(i-j)>=c和dis(i-j)<c兩種情況,分別計算就行(一開始就是這裡被卡住了,

如果dis(i-j)>c只要將它分為兩部分考慮,分別計算v1的速度耗時和v2速度耗時即可)。

 

程式碼:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 120;
double MIN(double a,double b)
{
    return a<b?a:b;
}
double dp[maxn],l[maxn]; //記錄每次的時間,為浮點型。 
int main(void
) { double x,y,timtu,num,num2; int len; //初始題中的變數均為整形,n個位置除外 int n,c,t; int v,v1,v2; int i,j; while(~scanf("%d",&len)) { scanf("%d%d%d",&n,&c,&t); scanf("%d%d%d",&v,&v1,&v2); for(i=1;i<=n;i++) scanf("%lf",&l[i]); l[
0]=0;l[n+1]=len; for(i=1;i<maxn;i++) dp[i]=INT_MAX;dp[0]=0; //初始化處理dp,比較min,所以初始化最大 timtu=len*1.0/v; for(i=1;i<=n+1;i++) { for(j=i-1;j>=0;j--) { if(j==0) //特殊情況 { num=l[i]-l[0]; if(num<=c) dp[i]=MIN(dp[i],dp[0]+1.0*num/v1); else { num2=1.0*c/v1; num-=c; num2+=1.0*num/v2; dp[i]=MIN(dp[i],dp[0]+num2); } } else { x=t;num=l[i]-l[j];y=1.0*num/v2; //x表示需要充電,y表示不用充電。 if(num<=c) x+=num*1.0/v1; else { x+=c*1.0/v1; num-=c; x+=num*1.0/v2; } dp[i]=MIN(dp[i],dp[j]+MIN(x,y)); } } } if(dp[n+1]>=timtu) printf("Good job,rabbit!\n"); else printf("What a pity rabbit!\n"); } return 0; }
View Code