P2904 [USACO08MAR]River Crossing S

原题链接

考察:线性dp

思路:

       很容易想到f[i][j]表示前i趟运了j头牛的最小时间(本蒟蒻虽然想到了但因为会T放弃了这个想法,所以会T的做法先想想看能不能优化啊啊啊)

       所以f[i][j] = f[i-1][k]+sum[j-k]+2*m(这里会在最后一次多算一次m,最后答案减去即可).最后答案是f[i][n]

       很明显三重循环直接T了,考虑优化,很容易想到分级那道题的优化方式,但是这道题用不了分级的优化.可以发现每个f[i][j]都要与<=j的f[i][k]比较 ,且后面的sum数组也是变量.也就是说j在k1处取最小值,但这j+1在k1处就不一定取最小值.

       这题不知道为什么能把i循环去掉,感觉很迷.

       根据其他题解说仔细观察,本蒟蒻唯一发现的是转移方程先更新f[k]再更新f[j]更新在f[k]的2*m会叠加在f[j]上,然后可以发现转移方程与i无关.

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <unordered_map>
 5 using namespace std;
 6 const int N = 2510;
 7 int sum[N],n,m,f[N];
 8 int solve()
 9 {
10     memset(f,0x3f,sizeof f);
11     f[0] = 0;
12     for(int j=1;j<=n;j++)
13     {
14         for(int k=0;k<=j;k++)
15             f[j] = min(f[k]+sum[j-k]+2*m,f[j]);
16     }
17     return f[n]-m;
18 }
19 int main() 
20 {
21     scanf("%d%d",&n,&m);
22     for(int i=1;i<=n;i++) scanf("%d",&sum[i]),sum[i]+=sum[i-1];
23     printf("%d\n",solve());
24     return 0;
25 }

 

posted @ 2021-04-01 22:22  acmloser  阅读(75)  评论(0编辑  收藏  举报