题目
题意:
主角要从一座塔中逃脱,每一层除了出口外,还有不超过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; }