• 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
    ");
    	else printf("%d
    ",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;
    }
    

      

  • 相关阅读:
    StratifiedKFold和KFold的区别(几种常见的交叉验证)
    剑指offer:用栈来建立队列
    剑指offer:斐波那契数列
    树状数组 gcd 查询 Different GCD Subarray Query
    Loadrunner的使用
    Loadrunner的使用
    MySQL Windows 环境安装
    RobotFrameWork 自动化环境搭建(基于 python3.6)
    MySQL Linux 环境安装
    【读书笔记】状态模式代码C#
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/4388567.html
Copyright © 2020-2023  润新知