zoukankan      html  css  js  c++  java
  • HDU 3681 Prison Break BFS+状态压缩DP

    思路:先BFS出关键点(起点,电池,开关)之间的最短路

    然后状态压缩DP dp[当前位置][状态]=电池电量

    二分答案即可

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <queue>
    using namespace std;
    const int N=16;
    #define for if(0); else for
    struct Point{
        int x,y;
        Point(){x=y=0;}
        Point(int xx,int yy){x=xx;y=yy;}
    };
    
    const int inf=0x0f0f0f0f;
    int n,m;
    Point que[N*N+100];
    int vis[N][N];
    int d[N][N];
    int td[N][N];
    char g[N][N];
    int no[N][N];
    Point P[N];
    int nG,nY,num;
    
    void bfs(int s,int d[],int td[][N]){
        for(int i=0;i<N;i++) d[i]=inf;
        d[s]=0;
        memset(vis,0,sizeof(vis));
        memset(td,0x0f,N*N*sizeof(int));
        int st=0,ed=0;
        int dx[4]={0,0,1,-1};
        int dy[4]={1,-1,0,0};
        que[ed++]=P[s];
        td[P[s].x][P[s].y]=0;
        vis[P[s].x][P[s].y]=1;
        while(st!=ed){
            Point cur=que[st++];
            int curdis=td[cur.x][cur.y];
            if(no[cur.x][cur.y]!=-1){
                d[no[cur.x][cur.y]]=curdis;
            }
            for(int i=0;i<4;i++){
                Point np=Point(cur.x+dx[i],cur.y+dy[i]);
                if(!vis[np.x][np.y] && g[np.x][np.y]!='D' && g[np.x][np.y]!=0){
                    vis[np.x][np.y]=1;
                    td[np.x][np.y]=curdis+1;
                    que[ed++]=np;
                }
            }
        }
    }
    int dp[15][1<<15];
    bool can(int maxbatt){
        int maxmask=1<<(num-1);
        int sta=maxmask-1;
        for(int i=0;i<num;i++) memset(dp[i],-1,maxmask*sizeof(int));
        dp[0][sta]=maxbatt;
        for(int stat=sta;stat>=0;stat--){
            for(int i=1;i<num;i++){
                int mm=1<<(i-1);
                for(int j=0;j<num;j++) if(j!=i) {
                    int cost=d[i][j];
                    if(dp[j][stat]-cost>=0) dp[i][stat]=max(dp[i][stat],dp[j][stat]-cost);
                    if(~stat&mm){
                        int prev=stat^mm;
                        if(i<=nG) {
                            if(dp[j][prev]-cost>=0) {
                                dp[i][stat]=maxbatt;
                            }
                        }else{
                            if(dp[j][prev]-cost>=0) dp[i][stat]=max(dp[i][stat],dp[j][prev]-cost);
                        }
                    }
                }
                if(stat<(1<<nG) && dp[i][stat]>=0) return true;
            }
        }
        return false;
    }
    
    int main() {
        while(scanf("%d%d",&n,&m)&&(n||m)){
            memset(g,0,sizeof(g));
            for(int i=1;i<=n;i++) scanf("%s",g[i]+1);
            nG=nY=num=0;
            memset(no,-1,sizeof(no));
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++) if(g[i][j]=='F') P[num]=Point(i,j),no[i][j]=num++;
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++) if(g[i][j]=='G') P[num]=Point(i,j),nG++,no[i][j]=num++;
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++) if(g[i][j]=='Y') P[num]=Point(i,j),nY++,no[i][j]=num++;
            for(int i=0;i<num;i++){
                bfs(i,d[i],td);
            }
            bool haveans=true;
            for(int i=nG+1;i<num;i++) if(d[0][i]==inf) haveans=false;
            int left=0,right=n*m;
            int mid,ans=-1;
            if(haveans){
                    while(left<=right){
                    mid=(left+right)>>1;
                    if(can(mid)){
                        ans=mid;
                        right=mid-1;
                    }else left=mid+1;
                }
            }
            if(nY==0) ans=0;
            printf("%d\n",ans);
        }
        return 0;
    }
  • 相关阅读:
    洛谷 P1387 最大正方形
    洛谷 P1508 Likecloud-吃、吃、吃
    洛谷 P1282 多米诺骨牌
    洛谷 P1880 [NOI1995]石子合并
    P1064 金明的预算方案 (依赖性背包问题)
    caioj 1114 树形动态规划(TreeDP)3.0:多叉苹果树【scy改编ural1018二叉苹果树】
    让Dev C++支持C++11
    1113: [视频]树形动态规划(TreeDP)8:树(tree)(树形dp状态设计总结)
    caioj 1112 树形动态规划(TreeDP)7:战略游戏
    caioj 1111 树形动态规划(TreeDP)6: 皇宫看守 (状态设计)
  • 原文地址:https://www.cnblogs.com/programCaiCai/p/HDU3681.html
Copyright © 2011-2022 走看看