zoukankan      html  css  js  c++  java
  • ACAG 0x01-4 最短Hamilton路径

    ACAG 0x01-4 最短Hamilton路径

    论为什么书上标程跑不过这道题……
    首先,这道题与今年CSP-S2的D1T3有着异曲同工之妙,那就是——都有$O(n!)$的做法!(大雾)
    这道题的正解是状压DP。
    对于任意时刻,我们可以使用一个$n$位二进制数,若其第$i$位为$1$,则表示第$i$个点已经被经过,反之未被经过。因此我们可以使用$f[i][j]$表示状态为二进制数$i$,目前处于点$j$时的最短路径。
    在起点时,有$f[1][0]=0$,即只经过了点$0$,而相应的状态就是只有最低位为$1$。
    记得要把$f$数组的其他值均初始化为$INF$。
    不难得到,我们要的最终结果是$f[(1<<n)-1][n-1]$,即经过所有点($i$的每一位都是$1$),处于终点$n-1$的最短路。
    而本题的状态转移方程为:
    $f[i][j]=min(f[i][j],f[i^(1<<j)][k]+dis[j][k])$ 当且仅当 (i>>j)&1=1(i>>k)&1=1
    其中,因为$j$只能被恰好经过一次,且$k$也被恰好经过一次,所以考虑所有这样的$k$取最小值即可。

    #include<bits/stdc++.h>
    #define N 20
    
    using namespace std;
    
    int n;
    int dis[N][N],f[1<<N][N];
    
    void Read() {
    	scanf("%d",&n);
    	for(int i=0;i<=n-1;i++) {
    		for(int j=0;j<=n-1;j++) {
    			scanf("%d",&dis[i][j]);
    		}
    	}
    	return;
    }
    
    void Solve() {
    	memset(f,0x3f,sizeof(f));
    	f[1][0]=0;
    	for(int i=1;i<=(1<<n)-1;i++) {
    		for(int j=0;j<=n-1;j++) {
    			if((i>>j)&1) {
    				for(int k=0;k<=n-1;k++) {
    					if((i>>k)&1) {
    						f[i][j]=min(f[i][j],f[i^(1<<j)][k]+dis[j][k]);
    					}
    				}
    			}
    		}
    	}
    	printf("%d",f[(1<<n)-1][n-1]);
    	return;
    }
    
    int main()
    {
    	Read();
    	Solve();
    	return 0;
    }
    
  • 相关阅读:
    判断是否为蜘蛛抓取
    js Date
    JavaScript_Date对象说明
    php过滤字符串函数
    js 高考倒计时
    php 修改数据编码
    php 二维数组冒泡排序
    PSD网页切图制作HTML全过程教程
    产品经理职责
    互联网产品设计
  • 原文地址:https://www.cnblogs.com/luoshui-tianyi/p/11901806.html
Copyright © 2011-2022 走看看