洛谷 P1220 关路灯
分析一下,明显的区间dp,我们以dp [i] [j] [1]表示在i 到j的路灯已关,且老张在j点的情况下所用功耗的最小值,dp [i] [j] [0]则表示老张在i点,接着就是区间dp部分,见代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
const int maxn=1e2;
inline int read(){
int ret=0;
int f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-'){
f=-f;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
ret=ret*10+(ch^'0');
ch=getchar();
}
return ret*f;
}
int n;
int sum[maxn];
int dp[maxn][maxn][3];//dp[i][j][1]表示i到j的路灯全部关闭且老张在右边,反之
int w[maxn];
int l[maxn];
int m;
int main(){
freopen("a.in","r",stdin);
// n=read();
// m=read();
cin>>n>>m;
for(int i=1;i<=n;i++){
// l[i]=read();
// w[i]=read();
cin>>l[i]>>w[i];
sum[i]=sum[i-1]+w[i];
}
memset(dp,127,sizeof(dp));
dp[m][m][0]=dp[m][m][1]=0;
for(int len=1;len<n;len++){
for(int i=1;len+i<=n;i++){
int j=len+i;
int ad=sum[n];
dp[i][j][1]=min(dp[i][j-1][1]+(l[j]-l[j-1])*(ad-(sum[j-1]-sum[i-1])),dp[i][j-1][0]+(l[j]-l[i])*(ad-(sum[j-1]-sum[i-1])));
dp[i][j][0]=min(dp[i+1][j][0]+(l[i+1]-l[i])*(ad-(sum[j]-sum[i])),dp[i+1][j][1]+(l[j]-l[i])*(ad-(sum[j]-sum[i])));
}
}
cout<<min(dp[1][n][0],dp[1][n][1]);
return 0;
}
来解释几点吧
因为要取最小值,便于min的取值,将dp数组初始化为较大的一个数
因为我们要最终取值为起点为老张的位置的情况
所以将老张初始位置的dp值设置为0。
大该就是这样了。