……

解题报告: luogu P1220

题目链接:P1220 关路灯
P3205 [HNOI2010]合唱队差不多。
我们仍用一维来维护上一个关灯是在左边(\(0\))还是右边(\(1\))。
然后可以得到动态转移方程:

\[dp_{i,j,0}=\min\{dp_{i+1,j,0}+val,dp_{i+1,j,1}+val\} \]

\[dp_{i,j,1}=\min\{dp_{i,j+1,1}+val,dp_{i,j+1,0}+val\} \]

\[val=\text{时间}×\text{没有关到的灯的总功率} \]

可以用前缀和优化一下,复杂度是常树很小(bushi 的 \(\mathcal O(n^2)\)

\(Code\):

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;

#define read(x) scanf("%d",&x)
#define inf 1e9
#define MAXN 55

int n,c;
int xa[MAXN],xb[MAXN];
int dp[MAXN][MAXN][3],sum[MAXN];
int a,b;

int main()
{
	read(n),read(c);
	for(int i=1;i<=n;i++) read(xa[i]),read(xb[i]);
	sum[0]=0;
	for(int i=1;i<=n;i++) sum[i]=sum[i-1]+xb[i];
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++) dp[i][j][0]=dp[i][j][1]=inf;
	}
	dp[c][c][0]=dp[c][c][1]=0;
	for(int i=c-1;i>=1;i--)
	{
		dp[i][c][0]=dp[i+1][c][0]+(xa[i+1]-xa[i])*(sum[i]+sum[n]-sum[c]);
	}
	for(int i=c+1;i<=n;i++)
	{
		dp[c][i][1]=dp[c][i-1][1]+(xa[i]-xa[i-1])*(sum[n]-sum[i-1]+sum[c-1]);
	}
	for(int l=c-1;l>=1;l--)
	{
		for(int r=c+1;r<=n;r++)
		{
			a=dp[l+1][r][0]+(xa[l+1]-xa[l])*(sum[l]+sum[n]-sum[r]);
			b=dp[l+1][r][1]+(xa[r]-xa[l])*(sum[l]+sum[n]-sum[r]);
			dp[l][r][0]=min(dp[l][r][0],min(a,b));
			a=dp[l][r-1][0]+(xa[r]-xa[l])*(sum[l-1]+sum[n]-sum[r-1]);
			b=dp[l][r-1][1]+(xa[r]-xa[r-1])*(sum[l-1]+sum[n]-sum[r-1]);
			dp[l][r][1]=min(dp[l][r][1],min(a,b));
		}
	}
	printf("%d\n",min(dp[1][n][0],dp[1][n][1]));
	return 0;
} 
posted @ 2020-05-01 09:13  童话镇里的星河  阅读(115)  评论(0编辑  收藏  举报