CSUOJ 1141——第四届河南省程序设计大赛

题目的意思是给你一个机器人,初始的时候在某一个给定的路灯位置,机器人要把路边所有的路灯关掉,每个路灯都有一个距离和一个功率,求要把所有的路灯关掉最小的最终能耗是多少?

题目是一个很明显的区间DP。可以这样考虑,机器人关掉一个区间的路灯后,一定停留在该区间的最左端或者最右端,而且必须包括起点,显然。

这样我们就可以区间dp了。

对于每一个含有初始位置的区间[i,j],只有两种位置使其最终的位置为j,那就是i和j-1。这样就得到了状态转移了。

接下来还有一个问题,就是怎么计算能耗呢?这样想,对于每个状态,表示关闭该区间的所有的灯后根据其所停留的位置,所有路灯的最小能耗总和。

所以我们可以对于每个路灯,用一个数组表示前面n个路灯的功耗总和,这样就可以dp了。

上代码:(效率还挺高的)

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #define maxn 1010
 5 using namespace std;
 6  
 7 int f[2][maxn][maxn],w[maxn],d[maxn],n,k,tep,tep1,tep2;
 8  
 9 int main()
10 {
11     while (scanf("%d",&n)!=EOF)
12     {
13         scanf("%d",&k);
14         for (int i=1; i<=n; i++) scanf("%d%d",&d[i],&w[i]),w[i]+=w[i-1];
15         memset(f,0x3f,sizeof f);
16         f[1][k][k]=f[0][k][k]=0;
17         for (int i=k; i>0; i--)
18             for (int j=k; j<=n; j++)
19             {
20                 if (i==j) continue;
21                 tep=w[n]-w[j]+w[i];
22                 tep1=tep*(d[i+1]-d[i])+f[0][i+1][j];
23                 tep2=tep*(d[j]-d[i])+f[1][i+1][j];
24                 f[0][i][j]=min(tep1,tep2);
25                 tep=w[n]-w[j-1]+w[i-1];
26                 tep1=tep*(d[j]-d[j-1])+f[1][i][j-1];
27                 tep2=tep*(d[j]-d[i])+f[0][i][j-1];
28                 f[1][i][j]=min(tep1,tep2);
29             }
30         printf("%d
",min(f[0][1][n],f[1][1][n]));
31     }
32     return 0;
33 }
如有转载,请注明出处(http://www.cnblogs.com/lochan)
原文地址:https://www.cnblogs.com/lochan/p/3364091.html