P1220 关路灯

原题链接

考察:区间dp

这题好像HDU 4283 可以往左或者往右走.但是这道题起始位置不确定,也就是说,i位置不一定是栈底.

非常详细的题解

思路:

        因为题目完全不一样,所以必须换一个思路.以f[i][j]表示灭掉[i,j]所有灯消耗的功率.首先明确老张灭灯只要路过了就会灭,因此最后的位置要么是左边要么是右边.这两边难以确定,所有要用状态记录.

        f[l][r][1]表示最后位置在[l,r]区间的r处,需要推到此状态可以由哪些状态转移而来.

        f[l][r][1] = f[l][r-1][0] + (s[r]-s[r-1])*(sum[l-1]+sum[n]-sum[r-1])//(从r-1->r的时间后,其他灯等待的时间)

        f[l][r][0] = f[l][r-1][1]+ (s[r]-s[l])*(sum[l-1]+sum[n]-sum[r-1])//(从l->r的时间后,其他灯等待的时间)

        大区间由小区间推导而来,记录一下dp方程如何推导之大佬想法:

填表法就是利用状态转移方程和上一个状态来推导出现在的状态(相当于知道已知条件,将答案填入)

刷表法就是利用当前的状态,把有关联的下一状态都推出来。  

  明确将当前状态当成最终状态,因此终状态只能由子状态推导而来.

       记忆化搜索会TLE,或者是我没写对....

 

 1 #include <iostream>
 2 #include <cstdio> 
 3 #include <cstring>
 4 using namespace std;
 5 const int N = 55,INF = 0x3f3f3f3f;
 6 int n,s[N],sum[N],f[N][N][2],m;
 7 void solve()
 8 {
 9     for(int len=2;len<=n;len++)
10       for(int l=1;l+len-1<=n;l++)
11       {
12           int r = l+len-1;
13           int a = f[l+1][r][0]+(s[l+1]-s[l])*(sum[l]+sum[n]-sum[r]);
14           int b = f[l+1][r][1]+(s[r]-s[l])*(sum[l]+sum[n]-sum[r]);
15           f[l][r][0] = min(a,b);
16           int c = f[l][r-1][0]+(s[r]-s[l])*(sum[l-1]+sum[n]-sum[r-1]);
17           int d = f[l][r-1][1]+(s[r]-s[r-1])*(sum[l-1]+sum[n]-sum[r-1]);
18           f[l][r][1] = min(c,d);
19       }
20 }
21 int main()
22 {
23     scanf("%d%d",&n,&m);
24     memset(f,0x3f,sizeof f);
25     for(int i=1;i<=n;i++)
26     {
27         scanf("%d%d",&s[i],&sum[i]);
28         sum[i]+=sum[i-1];
29     }
30     f[m][m][0] = f[m][m][1] = 0;
31     solve();
32     printf("%d\n",min(f[1][n][0],f[1][n][1]));
33     return 0;
34 }

 

posted @ 2021-04-05 14:57  acmloser  阅读(70)  评论(0编辑  收藏  举报