HDU 3681

也算难题,难在如何处理有些点可以无限次经过 问题。 这道题,其实很容易想到二分+TSP的状态压缩,但在处理上述问题时,确实没想到。题解是处理每一个Y或G或F点到其他YGF点的距离,BFS,这样就出现一个点只访问一次,而且即便在原图上重复经过某点,在重建的图也不会体现出来了。绝!

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

char map[16][16];
bool vis[16][16];
int cnt,dp[1<<16][16];
struct Node{
	int x,y;
}node[16];
int dis[16][16][16][16];
const int inf=(1<<30);
int n,m,fp,head,tail;
int dir[4][2]={
	{0,1},
	{0,-1},
	{1,0},
	{-1,0}
};
Node que[400];
int endfor;

bool ok(int x,int y){
	if(x>=0&&x<n&&y>=0&&y<m&&map[x][y]!='D'&&!vis[x][y]) return true;
	return false;
}

void bfs(Node start){
	Node tmp;
	vis[start.x][start.y]=true;
	que[tail++]=start;
	int step=0;
	while(head<tail){
		int sz=tail-head;
		step++;
		while(sz--){
			Node ss=que[head++];
			for(int i=0;i<4;i++){
				tmp.x=ss.x+dir[i][0];
				tmp.y=ss.y+dir[i][1];
				if(ok(tmp.x,tmp.y)){
					if(map[tmp.x][tmp.y]=='G'||map[tmp.x][tmp.y]=='Y'){
						dis[start.x][start.y][tmp.x][tmp.y]=step; 
				//		cout<<start.x<<" "<<start.y<<" "<<tmp.x<<" "<<tmp.y<<" "<<step<<endl;
					}
					que[tail++]=tmp;
					vis[tmp.x][tmp.y]=true;
				}
			}
		}
	}
}

bool check(int bat){
	memset(dp,-1,sizeof(dp));
	int alt=1<<cnt;
	dp[1<<fp][fp]=bat;
	for(int i=0;i<alt;i++){
		for(int j=0;j<cnt;j++){
			if(dp[i][j]==-1) continue;
			if((i&endfor)==endfor){
				if(dp[i][j]!=-1) return true;
			}
			for(int k=0;k<cnt;k++){
				if(dis[node[j].x][node[j].y][node[k].x][node[k].y]==-1) continue;
				if(i&(1<<k)) continue;
				if(dp[i][j]-dis[node[j].x][node[j].y][node[k].x][node[k].y]<0) continue;
				int tmp=dp[i][j]-dis[node[j].x][node[j].y][node[k].x][node[k].y];
				if(map[node[k].x][node[k].y]=='G') tmp=bat;
				if(tmp>dp[i|(1<<k)][k]) dp[i|(1<<k)][k]=tmp;
			}
		}
	}
	return false;
}


void slove(){
	int l=0,r=1000;
	int res=r;
	while(l<=r){
		int m=(l+r)/2;
		if(check(m)){
			res=m;
			r=m-1;
		}
		else l=m+1;
	}
	if(res==1000) printf("-1\n");
	else printf("%d\n",res);
}

int main(){
	while(scanf("%d%d",&n,&m),n||m){
		cnt=0;
		endfor=0;
		for(int i=0;i<n;i++){
			scanf("%s",map[i]);
	//		cout<<map[i]<<endl;
			for(int j=0;j<m;j++){
				if(map[i][j]=='F'){
					fp=cnt;
					node[cnt].x=i,node[cnt].y=j;
					cnt++;
				}
				else if(map[i][j]=='G'){
					node[cnt].x=i,node[cnt].y=j;
					cnt++;
				}
				else if(map[i][j]=='Y'){
					node[cnt].x=i,node[cnt].y=j;
					endfor+=(1<<cnt);
					cnt++;
				}
			}
		}
		memset(dis,-1,sizeof(dis));
		for(int i=0;i<cnt;i++){
			head=tail=0;
			memset(vis,false,sizeof(vis));
			bfs(node[i]);
		}
		slove();
	}
	return 0;
}

  

posted @ 2015-04-02 22:13  chenjunjie1994  阅读(153)  评论(0编辑  收藏  举报