• 20181029 T2 寻宝游戏


    小 S 正在玩一款寻宝游戏,这个游戏的目的是在有限的时间内寻到尽量多的宝藏。游
    戏的地图是一个n行m列的网格,每个网格可能是“.”、“#”、“*”、“S”四种字符的一
    种,分别表示空地、障碍、宝藏点和玩家位置。其中宝藏点一共有恰好k个,而玩家位置恰
    好有一个。
    小 S 控制的角色每秒可以向上下左右移动一格,不能走出边界或走到障碍上。当小 S
    走到了一个宝藏点时,她可以瞬间收集这里的宝藏(这个宝藏点将变成空地)。
    小 S 一共有T + 0.5秒时间行动,当时间截至游戏就会结束。小 S 想在游戏结束之前收
    集尽量多的宝藏(即到达的不同的宝藏点尽量多),你能帮帮她吗?


    让我考场心态爆炸的罪魁祸首,首先看一波数据范围

    直接上BFS肯定过不了,然后发现k的值只有15,肯定从这里入手

    先用bfs求出每两个点之间的距离,是O(nmk)的,OK没问题

    然后来看如何转移,开始的时候我还是有一点想写DP的,但是死活没有想到状态该如何定义

    然后就很弱智的写了一个全排列,还不够优秀,只拿了40分(常数小一点的话就是60)

    考完之后听讲,发现自己就是个弟

    请大家一定要记住下面的话

    全排列是可以用状态压缩来优化的

    首先定义数组dp[i][j]表示i状态的结尾是j的最小时间

    这样很容易就得出了转移方程,每次选择一个还没有走过的点,然后枚举从哪里转移

    具体看代码

    然后再所有时间符合规范的里面选择宝藏数量最大的

    下面给出代码:(注意,不是值越大的二进制数里的一就越多,被坑的很惨)

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<cstdlib>
    using namespace std;
    inline int rd(){
        int x=0,f=1;
        char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
        return x*f;
    }
    inline void write(int x){
        if(x<0) putchar('-'),x=-x;
        if(x>9) write(x/10);
        putchar(x%10+'0');
        return ;
    }
    int n,m;
    int k,t;
    char map[506][506];
    struct node{
        int x,y;
    }s[106];
    int cnt=1;
    int dis[106][106];
    int q1[1000006],q2[1000006];
    int v[1000006];
    int l=0,r=0;
    int book[506][506];
    int num[506][506];
    void bfs(int a){
        l=0,r=0;
        memset(q1,0,sizeof(q1));
        memset(q2,0,sizeof(q2));
        memset(book,0,sizeof(book));
        q1[++r]=s[a].x,q2[r]=s[a].y;
        book[s[a].x][s[a].y]=1;
        v[r]=0;
        while(l<r){
            int h1=q1[++l];
            int h2=q2[l];
            if(map[h1][h2]=='*'){
                dis[a][num[h1][h2]]=v[l];
            }
            if(h1-1>0&&!book[h1-1][h2]&&map[h1-1][h2]!='#'){
                book[h1-1][h2]=1;
                q1[++r]=h1-1;
                q2[r]=h2;
                v[r]=v[l]+1;
            }
            if(h1+1<=n&&!book[h1+1][h2]&&map[h1+1][h2]!='#'){
                book[h1+1][h2]=1;
                q1[++r]=h1+1;
                q2[r]=h2;
                v[r]=v[l]+1;
            }
            if(h2-1>0&&!book[h1][h2-1]&&map[h1][h2-1]!='#'){
                book[h1][h2-1]=1;
                q1[++r]=h1;
                q2[r]=h2-1;
                v[r]=v[l]+1;
            }
            if(h2+1<=m&&!book[h1][h2+1]&&map[h1][h2+1]!='#'){
                book[h1][h2+1]=1;
                q1[++r]=h1;
                q2[r]=h2+1;
                v[r]=v[l]+1;
            }
        }
        return ;
    }
    int p[106];
    int a[106];
    int dp[100006][20];
    int vis[10006];
    int ans=0;
    int f=0;
    int main(){
        p[0]=1;
        for(int i=1;i<=20;i++) p[i]=p[i-1]*2;
        n=rd(),m=rd(),k=rd(),t=rd();
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                cin>>map[i][j];
                if(map[i][j]=='S'){
                    s[1].x=i,s[1].y=j;
                    num[i][j]=1;
                }
                if(map[i][j]=='*'){
                    s[++cnt].x=i,s[cnt].y=j;
                    num[i][j]=cnt;
                }
            }
        }
        for(int i=1;i<=k+1;i++) bfs(i);
        memset(dp,127,sizeof(dp));
        dp[0][0]=0;
        for(int i=1;i<=k;i++) dp[1<<(i-1)][i]=dis[1][i+1];
        for(int i=1;i<=p[k];i++){
            for(int j=1;j<=k;j++){
                if(i&1<<j-1){
                    for(int v=1;v<=k;v++){
                        if(i&1<<v-1) continue;
                        dp[i|(1<<v-1)][v]=min(dp[i|(1<<v-1)][v],dp[i][j]+dis[j+1][v+1]);
                    }
                }
            }
        }
        for(int i=p[k];i>=0;i--){
            for(int j=1;j<=k;j++){
                if(dp[i][j]<=t){
                    int h=i;
                    int cnt=0;
                    while(h){
                        if(h%2==1) cnt++;
                        h/=2;
                    }
                    ans=max(ans,cnt);
                }
            }
        }
        write(ans);
        return 0;
    }

     

  • 相关阅读:
    Cisco ASR1002-X告警处理
    WLC5520无法通过无线客户端进行网管故障解决
    一键分享mob,方法二
    Java中堆内存和栈内存详解
    linux.linuxidc.com
    android中shape的使用(android:angle小解)
    Activity的Launch mode详解 :standard(默认), singleTop, singleTask和 singleInstance
    Android studio个人常用快捷键
    Android 公告新闻消息资讯之垂直滚动效果
    数据库设计相关
  • 原文地址:https://www.cnblogs.com/WWHHTT/p/9873850.html
Copyright © 2020-2023  润新知