蓝桥杯-第二点五个不高兴的小明-动态规划
题目:http://lx.lanqiao.cn/problem.page?gpid=T770
思路:
令dp[i][j]表示第i次跳跃跳到位置j时跳过的方格权重值
对于第i次跳跃。由于一次最多跳p格,而且不会跳出头,所以它的可能位置为[i,min(i*p)]
如果当前处在位置j,那么它上一次的位置 bef可能在[max(0,j-p),j-1] 上一次的位置不可能小于0
转移方程
dp[i][j]=max(dp[i][j], dp[i-1][bef]+w[j])
需要注意的是,题目中的w[i]可能为负数,那么在转移过程中可能出现怎么跳都比不跳更划算的情况,导致出现问题。所以需要预处理数据,把所有w[i]加上1000成为正数,最后结果里减去对应的多加的数。
1 #include <iostream> 2 #include <stdio.h> 3 //#define LOCAL 4 using namespace std; 5 typedef long long ll; 6 const int mx=1000+10; 7 const int inf=-1005*1005; 8 int n, p, t; 9 int w[mx]; 10 int dp[mx][mx];//dp[i][j] i times j sub 11 void solve(){ 12 cin>>n>>p>>t; 13 for(int i=1;i<=n;i++) cin>>w[i], w[i]+=1000; 14 for(int i=1;i<=t;i++) 15 for(int j=1;j<=n;j++) 16 dp[i][j]=inf; 17 t--; 18 for(int i=1;i<=t;i++){//time 19 for(int j=i;j<=min(n,i*p);j++){//sub 20 for(int bef=max(0,j-p);bef<=j-1;bef++){ 21 dp[i][j]=max(dp[i][j], dp[i-1][bef]+w[j]); 22 } 23 } 24 } 25 int ans=inf; 26 for(int i=n;i>=n-p+1;i--){ 27 ans=max(dp[t][i], ans); 28 } 29 ans-=1000*t; 30 cout<<ans<<endl; 31 } 32 33 int main(){ 34 #ifdef LOCAL 35 FILE *fp=freopen("1.txt", "r", stdin); 36 #endif // LOCAL 37 solve(); 38 #ifdef LOCAL 39 fclose(fp); 40 #endif // LOCAL 41 return 0; 42 }