ZOJ 3431 Escape! 解题报告

来源:互联网 发布:日经225指数数据分析 编辑:程序博客网 时间:2024/06/05 19:20

题目

题意:

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