zoukankan      html  css  js  c++  java
  • hdu3681 Prison Break

    二分电池容量。

    至于检查答案是否合法,我们注意到有用的点只有 F,G,Y,其他的点都是无用的。这三种点加起来最多 16 个(the sum of energy pools and power switches is less than 15)。我们就可以在图中找这三种点,对他们状压。

    具体地,令 (f(i,s)) 表示当前点为 (i),其他点的经过状态为 (s)(状态压缩)的最大剩余能量,则有 (f(j,scup{j})=max{f(i,s)-operatorname{dis}(i,j)})(operatorname{dis}(i,j)) 表示点 (i) 到点 (j) 的距离,用 bfs 预处理。我们初始化将所有 (f(i,s)) 赋为 (-1)(f(x,{x})=mid)(x) 为起点)。在 dp 过程中如果发现当前枚举的 (s) 包含了所有的 Y 点且 (f(i,s)) 不为 (-1),说明能够有一种方案使得所有 Y 点都被经过,直接 return true

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N=15,nxt[4][2]={0,1,1,0,0,-1,-1,0};
    int dp[N+10][(1<<N)+10];
    int n,m,dis[N*N+10][N*N+10];
    char s[N+10][N+10];
    bool vis[N+10][N+10];
    
    struct node
    {
    	int x,y,s;
    	node(int x,int y,int s) : x(x),y(y),s(s) {}
    	node() {}
    }p[N+10],que[N+10];
    int h=1,t=0;
    int bfs(int x,int y) // point x  to  point y
    {
    	memset(que,0,sizeof(que));
    	h=1;t=0;
    	memset(vis,0,sizeof(vis));
    	que[++t]=node(p[x].x,p[x].y,0);
    	vis[p[x].x][p[x].y]=1;
    	while(h<=t)
    	{
    		node head=que[h++];
    		if(head.x==p[y].x && head.y==p[y].y) return /*(puts("LHTDULIU"),*/head.s;
    		for(int i=0;i<4;i++)
    		{
    			int tx=head.x+nxt[i][0],ty=head.y+nxt[i][1];
    			if(vis[tx][ty] || s[tx][ty]=='D' || 
    			tx<1 || tx>n || ty<1 || ty>m) continue;
    			que[++t]=node(tx,ty,head.s+1); 
    			vis[tx][ty]=1;
    		}
    	}
    	return -1;
    }
    int st,cnt=0,ac=0;
    bool check(int en) // en:middle(energy)
    {
    	memset(dp,-1,sizeof(dp));
    	dp[st][1<<(st-1)]=en;
    	int all_state=1<<cnt; 
    	for(int sta=0;sta<all_state;sta++)
    	{
    		for(int i=1;i<=cnt;i++) //i:from
    		{
    			if(!(sta&(1<<(i-1)))) continue;
    			if(dp[i][sta]==-1) continue;
    			if((sta&ac)==ac) return true;
    			for(int j=1;j<=cnt;j++)
    			{
    				if(sta&(1<<(j-1))) continue;
    				if(dis[i][j]==-1) continue;
    				if(dp[i][sta]<dis[i][j]) continue;
    				int zzt=sta|(1<<(j-1)); 
    				dp[j][zzt]=max(dp[j][zzt],dp[i][sta]-dis[i][j]);
    				if(s[p[j].x][p[j].y]=='G') dp[j][zzt]=en;
    			}
    		}
    	}
    	return false; 
    }
    int main()
    {
    	while(~scanf("%d %d",&n,&m))
    	{
    		if(n==0 && m==0) break;
    		cnt=0;
    		ac=0;
    		for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
    		for(int i=1;i<=n;i++)
    		{
    			for(int j=1;j<=m;j++)
    			{ 
    				if(s[i][j]=='G')
    				{
    					p[++cnt]=node(i,j,0);
    				}
    				else if(s[i][j]=='F')
    				{
    					st=++cnt;
    					p[cnt]=node(i,j,0);
    				}
    				else if(s[i][j]=='Y')
    				{
    					cnt++;
    					ac|=(1<<(cnt-1));
    					p[cnt]=node(i,j,0);
    				}
    			}
    		}
    		memset(dp,-1,sizeof(dp));
    		memset(dis,-1,sizeof(dis));
    		for(int i=1;i<=cnt;i++)
    			for(int j=1;j<=cnt;j++)
    				dis[i][j]=dis[j][i]=bfs(i,j);
    		int l=1,r=10000,ans=-1;
    		while(l<=r)
    		{
    			int mid=(l+r)/2;
    			if(check(mid))
    			{
    				ans=mid;
    				r=mid-1;
    			}
    			else l=mid+1;
    		}
    		printf("%d",ans);
    		putchar('
    ');
    	}
    	return 0;
    }       
    /*
    5 5
    GDDSS
    SSSFS
    SYGYS
    SGSYS
    SSYSS
    5 5
    GDDSS
    SSSFS
    SYGYS
    SGSYS
    SSYSS
    5 5
    GDDSS
    SSSFS
    SYGYS
    SGSYS
    SSYSS
    0 0
    */
    
  • 相关阅读:
    使用tab与鼠标 的触发焦点事件差异
    UniteDataTable vb.net
    C#】#if DEBUG 与 如何更好更快的debug
    【刷题】[NOI2018] 你的名字 LuoguP4770/LOJ2720
    【学习笔记】【博弈论】信竞博弈论学习笔记_SG函数_纳什均衡
    【学习笔记】【数论】杜教筛及狄利克雷卷积及一些怪东西
    【CF】Codeforces 280D kMaximum Subsequence Sum 贪心/线段树/模拟费用流
    第五节 电能质量
    硬连接
    BSTR详解三 BSTR使用注意事项
  • 原文地址:https://www.cnblogs.com/juruo-zzt/p/13908190.html
Copyright © 2011-2022 走看看