• codevs 2800 送外卖 floyd + Tsp


    简单的状压动归

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=17;
    const long long INF=10000000+233;
    long long dp[1<<N][N],dis[N][N];
    int times(int s){
        int cnt=0;
        for(int k=0;(1<<k)<=s;++k)if(s&(1<<k))++cnt;
        return cnt;
    }
    int check(int s,int j)
    {
        if(s&(1<<(j-1)))return 1;
        return 0;
    }       //s中是否有j
    int main()
    {
        int n;scanf("%d",&n);
        for(int i=0;i<=n;++i)
            for(int j=0;j<=n;++j)
                if(i!=j)dis[i][j]=INF;
        for(int i=0;i<=n;++i)
            for(int j=0;j<=n;++j)
                scanf("%lld",&dis[i][j]);
        for(int k=0;k<=n;++k)
            for(int i=0;i<=n;++i)
                for(int j=0;j<=n;++j)
                    if(dis[i][j]>dis[i][k]+dis[k][j])dis[i][j]=dis[i][k]+dis[k][j];
        for(int S=1;S<(1<<n);++S)
            for(int j=1;j<=n;++j)
            {
                dp[S][j]=INF;
                if(check(S,j)==0)continue;
                int mx=S^(1<<(j-1));
                int cnt=times(mx);
                if(cnt==0){dp[S][j]=dis[0][j];continue;}    //只有一个元素
                for(int k=1;k<=n;++k)
                {
                    if(k==j||check(mx,k)==0)continue;
                    dp[S][j]=min(dp[S][j],dp[mx][k]+dis[k][j]);
                }
            }
        long long ans=INF;
        for(int i=1;i<=n;++i)
            ans=min(ans,dp[(1<<n)-1][i]+dis[i][0]);
        printf("%lld",ans);
        return 0;
    }
  • 相关阅读:
    Luogu 三国游戏
    牛客练习赛60E
    cf1321E
    cf988D
    cf1089F
    cf1055C
    cf997B
    cf1033D
    cf1062D
    cf1081E
  • 原文地址:https://www.cnblogs.com/guangheli/p/9845210.html
Copyright © 2020-2023  润新知