洛谷 P1220 关路灯 区间dp

洛谷 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。
大该就是这样了。

原文地址:https://www.cnblogs.com/rpup/p/13541926.html