• 【题解】灰化肥,会挥发


    题目链接

    题目大意:给定一张图(四联通),求图上从(A)点走完所有(key)点的最短路径,输出字典序最小的路径

    这里用一个小(trick):求出所有关键点两两之间的距离,就可以把图给扔了。

    考虑到(key)点的数量很少,考虑一波状压。

    设计状态(dp[i][j])表示当前点在(j),状态为(i)的最短路径。

    那么显然:

    [dp[i][j]=k:in j_{next} min(dp[i|(1<<k)][k],dp[i][j]+dis[j][k]) ]

    同时维护一个路径即可。需要注意的是,当枚举到更新状态和当前状态路径相同的时候,要注意字典序是不是可以更新。

    状压储存点从(0)开始比较好。注意的是,点需要保证第一个点是(A),否则不能保证正确。

    代码实现的细节比较多。位运算不要写错。

    注意这题卡空间。
    ( ext{Code:})

    #include<bits/stdc++.h>
    using namespace std;
    int r,c,n,last,pos;
    char mp[501][501];
    const int dx[4]={0,1,0,-1};
    const int dy[4]={1,0,-1,0};
    struct edge{int x,y;}p[16];
    int dp[1<<16][16],tot;
    int dis[16][16],u[501][501];
    string f[1<<16][16],res;
    void BFS(edge s){
    	queue<edge>q;
    	memset(u,0,sizeof(u));
    	q.push(s);u[s.x][s.y]=1;
    	while(!q.empty()){
    		edge tmp=q.front();q.pop();
    		for(int i=0;i<4;++i){
    			int x=tmp.x+dx[i],y=tmp.y+dy[i];
    			if(x<1||x>r||y<1||y>c||u[x][y]||mp[x][y]=='*')continue;
    			u[x][y]=u[tmp.x][tmp.y]+1;q.push((edge){x,y});
    		}
    	}
    }
    bool cmp(edge a,edge b){
    	return mp[a.x][a.y]<mp[b.x][b.y];
    }
    int main(){
    	scanf("%d%d%d",&r,&c,&n);
    	for(int i=1;i<=r;++i)
    		scanf("%s",mp[i]+1);
    	for(int i=1;i<=r;++i)
    		for(int j=1;j<=c;++j)
    			if(mp[i][j]>='A'&&mp[i][j]<='Z')p[tot++]=(edge){i,j};
    	sort(p,p+tot,cmp);
    	for(int i=0;i<tot;++i){
    		BFS(p[i]);
    		for(int j=0;j<tot;++j)dis[i][j]=u[p[j].x][p[j].y]-1;
    	}
    	
    	//for(int i=0;i<tot;++i)
    	//	for(int j=0;j<tot;++j)
    	//		cout<<mp[p[i].x][p[i].y]<<"->"<<mp[p[j].x][p[j].y]<<":"<<dis[i][j]<<endl;
    	
    	memset(dp,63,sizeof(dp));
    	dp[1][0]=0;f[1][0]="A";
    	for(int i=1;i<(1<<tot);++i){
    		if(!(i&1))continue;
    		for(int j=0;j<tot;++j){
    			if(!(i&(1<<j)))continue;//start->j
    			for(int k=1;k<tot;++k){
    				if(i&(1<<k))continue;//goal->k
    				if(dp[i|(1<<k)][k] > dp[i][j] + dis[j][k]){
    					dp[i|(1<<k)][k] =dp[i][j] + dis[j][k];
    					f[i|(1<<k)][k] =f[i][j] + mp[p[k].x][p[k].y];
    				}
    				else if(dp[i|(1<<k)][k] == dp[i][j] + dis[j][k])
    					if(f[i|(1<<k)][k] > f[i][j] + mp[p[k].x][p[k].y])
    						f[i|(1<<k)][k] = f[i][j] + mp[p[k].x][p[k].y];
    			}
    		}
    	}
    	last=(1<<tot)-1;
    	pos=dp[last][1];
    	res=f[last][1];
    	for(int i=2;i<tot;++i){
    		if(dp[last][i]<pos){
    			pos=dp[last][i];
    			res=f[last][i];
    		}
    		else if(dp[last][i]==pos&&res>f[last][i])res=f[last][i];
    	}
    	printf("%d
    ",pos);
    	cout<<res<<endl;
    	return 0;
    }
    /*
    20 20 5
    E......*...........*
    B.....*.............
    A................*..
    ..C............*....
    ..*..D....*.........
    *.*.*..............*
    ..*...*.......*.....
    ...............****.
    ....................
    ........*..........*
    ..*...........*.....
    ..*........*.*......
    **.*........*.......
    ..........*......*..
    ....*........*......
    *.*....*........*..*
    *.*...........*.*...
    .*..*......*........
    ......*.......*.....
    ...*......*.........
    */
    
  • 相关阅读:
    HDU 1890 Robotic Sort (splay tree)
    POJ 3468 A Simple Problem with Integers (splay tree入门)
    1588: [HNOI2002]营业额统计 (splay tree)
    HDU 4597 Play Game (DP,记忆化搜索)
    HDU 4499 Cannon (搜索)
    HDU 4497 GCD and LCM (合数分解)
    升级到 Android Studio 3.0 + Gradle 4.1 遇到的一些坑及解决方案
    关于The specified Android SDK Build Tools version (26.0.2) is ignored, as it is below the minimum...
    Android Studio启动时出现unable to access android sdk add-on list
    unable to access android sdk add-on list(转)
  • 原文地址:https://www.cnblogs.com/h-lka/p/12404022.html
Copyright © 2020-2023  润新知