P1220 关路灯 (有点不同的区间dp)
P1220 关路灯 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
本题有个很重要的信息:大爷是可以随手关灯,所以对于区间[i~j],出于贪心,大爷最后要么在 i 位置,要么在 j 位置。
令DP[i][j][0/1],为0时在 i 位置,为1时在 j 位置 关掉区间[ i , j ]所需的最少时间(这跟P3205 [HNOI2010]合唱队的dp状态很像)
考虑区间dp[i][j][0/1]的转移:
先考虑dp[i][j][0]。;
如果我们考虑 k 便是考虑 dp[i][k][0/1]与dp[k+1][j][0/1],但这也™的难写,而且在走的过程中,dp[i][k][0/1]与dp[k+1][j][0/1]直接好像没法联系一起,因为走的时候还要考虑其他亮着的灯消耗的功率。
但实际上dp[i][j][0]只会从dp[i+1][j][0/1]转移过来
对于dp[i+1][j][0]:dp[i][j][0]=dp[i+1][j][0]+(pos[i+1]-pos[i])*(sum[n]-(sum[j]-sum[i])).(从pos[i+1]走到pos[i],其他的灯还是亮着会消耗,这一段很容易忘写)
对于dp[i+1][j][1]:dp[i][j][0]=dp[i+1][j][1]+(pos[j]-pos[i])*(sum[n]-(sum[j]-sum[i])).
所以:dp[i][j][0]=min(dp[i+1][j][0]+(pos[i+1]-pos[i])*(sum[n]-(sum[j]-sum[i])),
dp[i+1][j][1]+(pos[j]-pos[i])*(sum[n]-(sum[j]-sum[i])));
对于dp[i][j][1]同理。
dp[i][j][1]也只会从dp[i][j-1][0/1]转移过来
与dp[i][j][0]转移同理
初始化:dp[i][i][0/1]=INF,dp[c][c][0/1]=0;这道题不用dp[i][j][0/1]=INF,因为dp[i][j][0/1]不需要min(dp[i][j][0/1]);
Code:
#include<bits/stdc++.h> using namespace std; #define ll long long #define mp make_pair #define pb push_back #define popb pop_back #define fi first #define se second const int N=110; //const int M=; //const int inf=0x3f3f3f3f; const ll INF=0x3ffffffffffff; int T,n,c,pos[N],w[N]; ll dp[N][N][3],sum[N]; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } int main() { // freopen("","r",stdin); // freopen("","w",stdout); n=read(),c=read(); for(int i=1;i<=n;i++) { pos[i]=read();w[i]=read(); sum[i]=sum[i-1]+w[i]; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) dp[i][i][0]=dp[i][i][1]=INF; dp[c][c][0]=dp[c][c][1]=0; for(int len=2;len<=n;len++) for(int i=1;i+len-1<=n;i++) { int j=i+len-1; dp[i][j][0]=min(dp[i+1][j][0]+(pos[i+1]-pos[i])*(sum[n]-(sum[j]-sum[i])), dp[i+1][j][1]+(pos[j]-pos[i])*(sum[n]-(sum[j]-sum[i]))); dp[i][j][1]=min(dp[i][j-1][0]+(pos[j]-pos[i])*(sum[n]-(sum[j-1]-sum[i-1])), dp[i][j-1][1]+(pos[j]-pos[j-1])*(sum[n]-(sum[j-1]-sum[i-1]))); } printf("%lld",min(dp[1][n][0],dp[1][n][1])); return 0; }