模拟赛 T3 room
可以看出,n很小,不超过14,所以有很多做法。
可以状压DP、记忆化搜索。
下面是有点奇怪的做法……,不是很好理解。(有点像状压……吧)(没来得及加注释)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n,ro[16],go[16],rk[16],gk[16],wk[16],key[16],f[20010][210],tot,ans;
int main()
{
freopen("room.in","r",stdin);
freopen("room.out","w",stdout);
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&ro[i]);
for(int i=0;i<n;i++) scanf("%d",&go[i]);
for(int i=0;i<n;i++) scanf("%d",&rk[i]);
for(int i=0;i<n;i++) scanf("%d",&gk[i]);
for(int i=0;i<n;i++) scanf("%d",&wk[i]);
scanf("%d%d%d",&key[0],&key[1],&key[2]);
tot=key[0]+key[1]+key[2];
memset(f,-1,sizeof(f));
f[0][key[0]]=key[2];
for(int i=0;i<(1<<n);i++)
{
int k0=key[0],k1=key[1],r=tot;
for(int j=0;j<n;j++)
if((i>>j)&1)
{
k0+=rk[j];
r+=rk[j]+gk[j]+wk[j]-ro[j]-go[j];
}
for(int j=0;j<=k0;j++)
{
if(f[i][j]==-1) continue;
int t=r-f[i][j]-j;
for(int k=0;k<n;k++)
{
if((i>>k)&1) continue;
int p=max(0,ro[k]-j),q=max(0,go[k]-t);
int &h=f[i|(1<<k)][max(0,j-ro[k])+rk[k]];
if(f[i][j]>=p+q)
h=max(h,f[i][j]-p-q+wk[k]);
}
ans=max(ans,j+t+f[i][j]);
}
}
printf("%d\n",ans);
return 0;
}
还有记忆化搜索的。
记忆化搜索就很棒了,很好理解。(注释比较详细就不多说了)(还是要状态压缩)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,ans,ro[16],go[16],rk[16],gk[16],wk[16],r,g,w;
bool v1[100005],v2[16];//v1存是否搜过该状态,v2存是否开过该密室
void dfs(int no,int r,int g,int w)//no用二进制表示状态
{
if(v1[no]) return;//剪枝,搜过该状态就不用再搜了
ans=max(ans,r+g+w);//更新答案
v1[no]=1;//将该状态记为搜过
for(int i=1;i<=n;i++)
if(!v2[i])
{
int r_=r-ro[i],g_=g-go[i],w_=w+min(r_,0)+min(g_,0);
if(w_<0) continue;//用白色钥匙无法补齐红、绿钥匙与锁的差距
r_=max(r_,0)+rk[i];
g_=max(g_,0)+gk[i];
w_+=wk[i];
v2[i]=1;//将该密室记为开过
dfs(no|(1<<(i-1)),r_,g_,w_);//当前状态下继续搜
v2[i]=0;//回溯
}
}
int main()
{
freopen("room.in","r",stdin);
freopen("room.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&ro[i]);
for(int i=1;i<=n;i++) scanf("%d",&go[i]);
for(int i=1;i<=n;i++) scanf("%d",&rk[i]);
for(int i=1;i<=n;i++) scanf("%d",&gk[i]);
for(int i=1;i<=n;i++) scanf("%d",&wk[i]);
scanf("%d%d%d",&r,&g,&w);
dfs(0,r,g,w);
printf("%d\n",ans);
return 0;
}