题意:
主角要从一座塔中逃脱,每一层除了出口外,还有不超过5个的宝藏,而且每层还有倒塌时间。求在成功离开的前提下,能拿到的最大财宝价值。
题解:
对每一层做预处理,计算从入口选择某几个宝藏再到出口所花的最少时间。然后对每层做dp[i],i表示到这层的时间为i,然后枚举所有选宝藏的方案来转移。
//Time:190ms
//Memory:280KB
//Length:2647B
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAXN 105
#define MAXT 1300
#define INF 1000000007
int n;
int x[MAXN],y[MAXN],num[MAXN],ti[MAXN];
int px[MAXN][10],py[MAXN][10],v[10],dp_t[MAXN][32][5],val[MAXN][32];
int dp[2][MAXT];
int main()
{
//freopen("/home/moor/Code/input","r",stdin);
int cas;
scanf("%d",&cas);
while (cas--)
{
scanf("%d",&n);
for (int i=0;i<=n;i++) scanf("%d%d",&x[i],&y[i]);
memset(dp_t,0x3f,sizeof(dp_t));
memset(val,0,sizeof(val));
for (int i=1;i<=n;i++)
{
scanf("%d",&num[i]);
for (int j=0;j<num[i];j++)
scanf("%d%d%d",&px[i][j],&py[i][j],&v[j]);
for (int j=0;j<(1<<num[i]);j++)
for (int k=0;k<num[i];k++)
if ((j&(1<<k))!=0) val[i][j]+=v[k];
for (int j=0;j<num[i];j++)
dp_t[i][(1<<j)][j]=abs(x[i-1]-px[i][j])+abs(y[i-1]-py[i][j]);
for (int j=0;j<(1<<num[i]);j++)
for (int pre=0;pre<num[i];pre++)
if ((j&(1<<pre))!=0)
for (int now=0;now<num[i];now++)
if ((j&(1<<now))==0)
{
int sta=j|(1<<now);
dp_t[i][sta][now]=min(dp_t[i][j][pre]+abs(px[i][pre]-px[i][now])+abs(py[i][pre]-py[i][now]),dp_t[i][sta][now]);
}
}
for (int i=1;i<=n;i++) scanf("%d",&ti[i]);
memset(dp,-0x3f,sizeof(dp));
dp[0][0]=0;
int s=1;
for (int i=1;i<=n;i++)
{
memset(dp[s],-0x3f,sizeof(dp[s]));
for (int t=0;t<=ti[i];t++)
if (dp[!s][t]>-INF)
{
int tmp=t+abs(x[i]-x[i-1])+abs(y[i]-y[i-1]);
if (tmp<=ti[i])
dp[s][tmp]=max(dp[s][tmp],dp[!s][t]);
for (int k=0;k<num[i];k++)
{
for (int j=0;j<(1<<num[i]);j++)
{
tmp=t+dp_t[i][j][k]+abs(x[i]-px[i][k])+abs(y[i]-py[i][k]);
if (tmp<=ti[i])
dp[s][tmp]=max(dp[s][tmp],dp[!s][t]+val[i][j]);
}
}
}
s=!s;
}
int ans=-INF;
for (int t=0;t<=ti[n];t++)
ans=max(ans,dp[!s][t]);
if (ans<=-INF) printf("I'm doomed, though I fought bravely\n");
else printf("%d\n",ans);
}
return 0;
}