A sample Hamilton path(状压DP)

A sample Hamilton path(状压DP)

传送门

思路:看到 n n n的范围最大是 22 22 22,想到应该是用 2 22 2^{22} 222的算法,所以很容易想到用状压 d p dp dp

d p [ s t a t u s ] [ e n d ] dp[status][end] dp[status][end]表示状态 i i i时终点为 e n d end end的最短哈密顿路。

至于优先级用一个数组存在一下每个结点前面的结点有那些,用二进制存即可。

转移的时候特判一下不能转移的状态即可。注意初始化的时候不要用 m e m s e t memset memset初始化 d p dp dp。会导致 M L E MLE MLE

AC代码:

#include
using namespace std;
typedef long long ll;
const int N=(1<<21),inf=0x3f3f3f3f;
#define mst(a) memset(a,0,sizeof a)
int dp[N][22],n,m,dis[22][22],st[22];
int main(){
     
	while(~scanf("%d%d",&n,&m)){
     
	memset(dis,0,sizeof dis);
	memset(st,0,sizeof dis);
	//memset(dp,0x3f,sizeof dp);
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			scanf("%d",&dis[i][j]);
	for(int i=1,u,v;i<=m;i++){
     
		scanf("%d%d",&u,&v);
		st[v]|=(1<<u); 
	}
	for(int i=0;i<(1<<n);i++)
		for(int j=0;j<n;j++)
			dp[i][j]=inf; 
	dp[1][0]=0;
	for(int k=0;k<(1<<n);k++)
		for(int i=0;i<n;i++)
				if(dp[k][i]!=inf)
			for(int j=0;j<n;j++){
     
				 if(dis[i][j]==-1||(!(k&(1<<i)))||(k&(1<<j))||st[j]!=(st[j]&k)) continue;
				 dp[k|(1<<j)][j]=min(dp[k|(1<<j)][j],dp[k][i]+dis[i][j]);
			}
	int ans=inf;
	for(int i=0;i<n;i++) ans=min(ans,dp[(1<<n)-1][i]);
	if(ans==inf) puts("-1");
	else printf("%d\n",ans);
	}
    return 0;
}

你可能感兴趣的:(DP)