zoukankan      html  css  js  c++  java
  • 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;
    }

     

  • 相关阅读:
    4 Apr 18 软件开发目录 logging模块的使用 序列化(Json, Pickle) os模块
    3 Apr 18 内置函数 列表生成式与生成器表达式 模块的使用之import 模块的使用之from…import…
    2 Apr 18 三元表达式 函数递归 匿名函数 内置函数
    30 Mar 18 迭代器 生成器 面向过程的编程
    29 Mar 18 函数 有参、无参装饰器
    28 Mar 18 函数
    27 Mar 18 函数的参数
    26 Mar 18 函数介绍
    23 Mar 18 文件处理
    22 Mar 18 补充数据类型+字符编码+文件处理
  • 原文地址:https://www.cnblogs.com/WWHHTT/p/9873850.html
Copyright © 2011-2022 走看看