区间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]);
分析:
首先走过的雕像一定是连续的一段区间 并且最终一定在一段区间的两边
所以转移的过程 就没必要枚举中间变量 因为[L,R] 一定是从[L-1,R] 或者 [L,R+1] 转移过来
又因为时间太大 不能将时间放入dp维度中 所以换个思路 不妨将时间变为dp结果
dp[i][j][k][0] 表示区间[i,j]收集了k个雕像 并且最终在左端点 所花的最少时间
dp[i][j][k][1] 表示区间[i,j]收集了k个雕像 并且最终在右端点 所花的最少时间
读清题目!!!起点是固定的!!!!
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#define LL long long
using namespace std;
const int kN=205;
const int kInf=0x3f3f3f3f;
int n,l;
int x[2*kN],t[2*kN];
int f[2*kN][2*kN][kN][2];
int ans;
int main(){
scanf("%d%d",&n,&l);
for(int i=1;i<=n;++i){
scanf("%d",&x[i]);
x[i+n+1]=x[i]+l;//将位置复制一份
}
for(int i=1;i<=n;++i){
scanf("%d",&t[i]);
t[i+n+1]=t[i];//将时间复制一份
}
memset(f,0x3f,sizeof f);
t[n+1]=-kInf;x[n+1]=l;
//n+1对应着起点
for(int i=n+1;i<=(n<<1)+1;++i){
for(int j=n+1;j&&i-j<=n;--j){
f[j][i][0][0]=l-x[j];
f[j][i][0][1]=x[i]-l;//初始化k=0的状态
}
}
for(int i=n+1;i<=(n<<1)+1;++i){
for(int j=n+1;j&&i-j<=n;--j){//保证区间<=n
for(int k=1;k<=i-j;++k){
f[j][i][k][0]=min(f[j][i][k][0],f[j+1][i][k][0]+(x[j+1]-x[j]));
if(f[j+1][i][k-1][0]+x[j+1]-x[j]<=t[j])
f[j][i][k][0]=min(f[j][i][k][0],f[j+1][i][k-1][0]+(x[j+1]-x[j]));
f[j][i][k][0]=min(f[j][i][k][0],f[j+1][i][k][1]+(x[i]-x[j]));
if(f[j+1][i][k-1][1]+x[i]-x[j]<=t[j])
f[j][i][k][0]=min(f[j][i][k][0],f[j+1][i][k-1][1]+(x[i]-x[j]));
f[j][i][k][1]=min(f[j][i][k][1],f[j][i-1][k][1]+(x[i]-x[i-1]));
if(f[j][i-1][k-1][1]+x[i]-x[i-1]<=t[i])
f[j][i][k][1]=min(f[j][i][k][1],f[j][i-1][k-1][1]+(x[i]-x[i-1]));
f[j][i][k][1]=min(f[j][i][k][1],f[j][i-1][k][0]+(x[i]-x[j]));
if(f[j][i-1][k-1][0]+x[i]-x[j]<=t[i])
f[j][i][k][1]=min(f[j][i][k][1],f[j][i-1][k-1][0]+(x[i]-x[j]));
if(f[j][i][k][0]<kInf)
ans=max(ans,k);
if(f[j][i][k][1]<kInf)
ans=max(ans,k);
}
}
}
printf("%d",ans);
return 0;
}