区间dp复习提高专题


这是一道非常典型的区间dp

for(int i=2*n-1;i>=1;i--)
for(int j=i+1;j<=2*n;j++)
for(int k=i;k<j;k++)
f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+a[i]*a[k+1]*a[j+1]);
int maxn=0;
for(int i=1;i<=n;i++)
maxn=max(f[i][i+n-1],maxn);


这个题就没有枚举中间变量k
而是向两边扩展的
对于每个区间终极状态老头不知道在左边还是右边
于是新加一维
dp[i][j][0]表示关完区间[i,j]的灯后老头在左边
反之 在右边

f[c][c][0]=f[c][c][1]=0;//瞬间被关(初始化)
  for(int l=2;l<=n;l++)
    for(int i=1;i+l-1<=n;i++)
      {
    int j=i+l-1;
    f[i][j][0]=min(f[i+1][j][0]+(a[i+1]-a[i])*(sum[i]+sum[n]-sum[j]),//继续走下去会更快吗?
               f[i+1][j][1]+(a[j]-a[i])*(sum[i]+sum[n]-sum[j]));//还是从j点折返回来会更快?(此时假设[i+1][j]被关,i亮,从j端点往回赶去关i)
//要注意的一点是sum[n]-(sum[j]-sum[i])是包括了i这一点的电能的,因为走过来的过程中灯i也会耗电
    f[i][j][1]=min(f[i][j-1][0]+(a[j]-a[i])*(sum[i-1]+sum[n]-sum[j-1]),//同上
               f[i][j-1][1]+(a[j]-a[j-1])*(sum[i-1]+sum[n]-sum[j-1]));
        }
  int ans=min(f[1][n][0],f[1][n][1]);


这个题和第一个题很类似,都是合并类型
最大最小就在另开一维数组

f[i][j][0]=max(f[i][j][0],f[i][k][0]+f[k+1][j][0]+s[j]-s[i-1]);
f[i][j][1]=min(f[i][j][1],f[i][k][1]+f[k+1][j][1]+s[j]-s[i-1]);


这个题类似之前那个灯泡
dp[i][j][0]表示走完区间[i,j]最终在i时最大数
dp[i][j][1]表示走完区间[i,j]最终在i时最小费时
dp[i][j][2]表示走完区间[i,j]最终在j时最大数
dp[i][j][3]表示走完区间[i,j]最终在j时最小费时
我的代码样例都过了但是re了,搞不懂

#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
#define ll long long
const int maxn=205;
ll n,L;
ll x[maxn],t[maxn];
ll dp[maxn][maxn][5];//0-1 2-3
int main(){
	cin>>n>>L;
	for(int i=1;i<=n;i++)cin>>x[i],x[i+n+1]=x[i];x[n+1]=x[2*n+2]=L;
	for(int i=1;i<=n;i++)cin>>t[i],t[i+n+1]=t[i];t[n+1]=t[2*n+2]=1e9; 
	for(int i=1;i<=maxn*2;i++)
	for(int j=1;j<=maxn*2;j++)
	dp[i][j][1]=dp[i][j][3]=1e8;
	dp[n+1][n+1][1]=dp[n+1][n+1][3]=dp[2*n+2][2*n+2][1]=dp[2*n+2][2*n+2][3]=0;
	for(int l=2;l<=n+1;l++){
		for(int i=1;i+l-1<=n*2+2;i++){
			ll j=l+i-1;
			ll t1=dp[i+1][j][1]+(x[i+1]-x[i]>0?x[i+1]-x[i]:x[i+1]-x[i]+L);
			ll t2=dp[i+1][j][3]+(x[j]-x[i]>0?x[j]-x[i]:x[j]-x[i]+L);
			ll t3=dp[i][j-1][3]+(x[j]-x[j-1]>0?x[j]-x[j-1]:x[j]-x[j-1]+L);
			ll t4=dp[i][j-1][1]+(x[j]-x[i]>0?x[j]-x[i]:x[j]-x[i]+L);
			ll dp1=dp[i+1][j][0]+(t1<=t[i]);
			ll dp2=dp[i+1][j][2]+(t2<=t[i]);
			ll dp3=dp[i][j-1][2]+(t3<=t[j]);
			ll dp4=dp[i][j-1][0]+(t4<=t[j]);
			if(dp1>dp2)dp[i][j][0]=dp1,dp[i][j][1]=t1;
			else if(dp1==dp2)dp[i][j][0]=dp1,dp[i][j][1]=min(t1,t2);
			else dp[i][j][0]=dp2,dp[i][j][1]=t2;
			if(dp3>dp4)dp[i][j][2]=dp3,dp[i][j][3]=t3;
			else if(dp3==dp4)dp[i][j][2]=dp3,dp[i][j][3]=min(t3,t4);
			else dp[i][j][2]=dp4,dp[i][j][3]=t4;
		}
	}
	ll ans=0;
	for(int i=1;i<=n+1;i++)
		ans=max(ans,max(dp[i][i+n][0],dp[i][i+n][2]));
	cout<<ans<<endl;
     return 0;
}
原文地址:https://www.cnblogs.com/wzxbeliever/p/15666511.html