您的位置:首页 > 其它

【洛谷1220】关路灯

2017-08-08 23:38 253 查看
题目链接:https://www.luogu.org/problem/show?pid=1220

题解:

- 我们发现它关的路灯一定是一个连续的区间,而且关掉一个区间的灯时,这个人一定在区间的左端点和右端点,那么我们考虑可以拿区间DP做

- 用f[i][j][0/1]表示关掉[i,j]区间的灯时花费的最少的功耗,0/1表示人此时在左端/右端,那么只要求一个功率的前缀和就能O(1)地转移,

dp方程推一推就出来了

/*f[i][j][0]=min(
f[i+1][j][0]+(pos[i+1]-pos[i])*(sum[i]+sum
-sum[j]),
f[i+1][j][1]+(pos[j]-pos[i])*(sum[i]+sum
-sum[j])
)
f[i][j][1]=min(
f[i][j-1][0]+(pos[j]-pos[i])*(sum[i-1]+sum
-sum[j-1]),
f[i][j-1][1]+(pos[j]-pos[j-1])*(sum[i-1]+sum
-sum[j-1])
) */


//by sdfzchy
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=60;
int f[100][100][2],n,w
,pos
,c,sum
;

int main()
{
scanf("%d%d",&n,&c);
for(int i=1;i<=n;i++) scanf("%d%d",&pos[i],&w[i]),sum[i]=sum[i-1]+w[i];
memset(f,0x3f,sizeof(f));
f[c][c][0]=f[c][c][1]=0;
for(int i=c+1;i<=n;i++)
{
f[c][i][1]=f[c][i-1][1]+(pos[i]-pos[i-1])*(sum
-sum[i-1]+sum[c-1]);
f[c][i][0]=f[c][i][1]+(pos[i]-pos[c])*(sum
-sum[i]+sum[c-1]);
}
for(int i=c-1;i;i--)
{
f[i][c][0]=f[i+1][c][0]+(pos[i+1]-pos[i])*(sum[i]+sum
-sum[c]);
f[i][c][1]=f[i][c][0]+(pos[c]-pos[i])*(sum[i-1]+sum
-sum[c]);
}

for(int i=c-1;i;i--)
for(int j=c+1;j<=n;j++)
{
f[i][j][0]=min(f[i+1][j][0]+(pos[i+1]-pos[i])*(sum[i]+sum
-sum[j]),f[i+1][j][1]+(pos[j]-pos[i])*(sum[i]+sum
-sum[j]));
f[i][j][1]=min(f[i][j-1][0]+(pos[j]-pos[i])*(sum[i-1]+sum
-sum[j-1]),f[i][j-1][1]+(pos[j]-pos[j-1])*(sum[i-1]+sum
-sum[j-1]));
}
printf("%d\n",min(f[1]
[0],f[1]
[1]));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: