POJ3311 Hie with the Pie(floyd+状压)

分析:
本题是一道经典的TSP问题,但是不同的是,这个题目他每个点可以走很多次,这也就意味着我们需要用最短路算法来求两点之间的最小距离。
本题数据范围很小,因此用floyd傻瓜算法是代码量最小的,floyd的本质是动态规划,过程是枚举每一个点作为中间节点
之后就用状压dp来做,我在查询资料的时候发现,因为最后要回到0点,所以很多人有不同的做法,有些人把n++,让第一位作为0点,我觉得没有必要。
这样思考容易在代码上出错,因此我提供一种比较好的状态设计,我们还是将第0位到第n-1位作为1-n这些点,然后枚举点数的时候从1枚举到n,而不是从0-n-1
但是在右移计算的时候,将点数-1运算,这样就和普通的状压一毛一样,具体可结合注释观看。

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<string> 
#include<set>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=13;
const int inf=0x3f3f3f3f;
int g[N][N];
int f[1<<N][N];
int n; 
void floyd(){
    int i,j,k;
    for(k=0;k<=n;k++){
        for(i=0;i<=n;i++){
            for(j=0;j<=n;j++){
                g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
            }
        }
    }
}
int main(){
    int i,j,k;
    while(cin>>n,n){
    for(i=0;i<=n;i++){
        for(j=0;j<=n;j++)
        cin>>g[i][j];
    }
    floyd();
    memset(f,0x3f,sizeof f);
    f[0][0]=0;
    for(i=0;i<1<<n;i++){
        for(j=1;j<=n;j++){//枚举1-n这些点 
            if((i>>(j-1))&1){//但是位置对应的是0-n-1,所以-1 
                if(i==(1<<(j-1)))
                f[i][j]=g[0][j];
                else{
                for(k=1;k<=n;k++){ 
                    if(k==j)
                    continue;
                    if((i>>(k-1))&1){
                        f[i][j]=min(f[i][j],f[i-(1<<(j-1))][k]+g[k][j]);
                    }
                }    
                }
            }
        }
    }
    int res=0x3f3f3f3f;
    for(i=1;i<=n;i++){//这样f[(1<<n)-1][i]中存的就是从遍历完所有点的最短消费,之后回到原点 
        res=min(res,f[(1<<n)-1][i]+g[i][0]);
    }
    cout<<res<<endl;
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/ctyakwf/p/12388624.html