• HDU 3001【状态压缩DP】


    题意:

    给n个点m条无向边。

    要求每个点最多走两次,要访问所有的点给出要求路线中边的权值总和最小。

    思路:

    三进制状态压缩DP,0代表走了0次,1,2类推。

    第一次弄三进制状态压缩DP,感觉重点是对数据的预处理,利用数组分解各个位数,从而达到类似二进制的目的。

    然后就是状态的表示,dp[s][i]表示状态s时到达i的最优值。

    状态转移也一目了然,不废话。

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    const int inf=0x3f3f3f3f;
    int pho[15][15];
    int unit[12];
    int dic[60000][11];
    int dp[60000][11];
    inline void init()
    {
        memset(dic,0,sizeof(dic));
        unit[0]=1;
        for(int i=1;i<=11;i++)
        {
            unit[i]=3*unit[i-1];
        }
        for(int i=0;i<=59049;i++)
        {
            int tmp=i;
            for(int j=0;tmp;j++)
            {
                dic[i][j]=tmp%3;
                tmp/=3;
            }
        }
    }
    int main()
    {
        int n,m;
        init();
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    pho[i][j]=inf;
                }
                pho[i][i]=0;
            }
            for(int i=1;i<=m;i++)
            {
                int a,b,c;
                scanf("%d%d%d",&a,&b,&c);
                pho[a][b]=pho[b][a]=min(pho[a][b],c);
            }
            int ed=1;
            for(int i=1;i<=n;i++)
            {
                ed*=3;
            }
            ed--;
            for(int s=0;s<=ed;s++)
            {
                for(int i=1;i<=n;i++)
                {
                    dp[s][i]=inf;
                }
            }
            bool ok;
            int ans=inf;
            for(int s=0;s<=ed;s++)
            {
                ok=1;
                for(int i=1;i<=n;i++)
                {
                    if(dic[s][i-1])
                    {
                        if(s==unit[i-1])
                        {
                            dp[s][i]=0;
                        }
                        else
                        {
                            for(int k=1;k<=n;k++)
                            {
                                if(i!=k&&(dic[s][k-1]))
                                {
                                    dp[s][i]=min(dp[s][i],dp[s-unit[i-1]][k]+pho[k][i]);
                                }
                            }
                        }
                    }
                    else
                    {
                        ok=0;
                    }
                }
                if(ok)
                {
                    for(int i=1;i<=n;i++)
                    {
                        ans=min(ans,dp[s][i]);
                    }
                }
            }
            if(ans>=inf)
                ans=-1;
            printf("%d
    ",ans);
        }
    }
  • 相关阅读:
    晚上打死个老鼠
    今早服务器出现的问题
    打球
    出于对Atlas自带AutoCompleteBehavior的不满,自定义了一个支持模版的AutoCompleteBehavior
    PetShop4.0项目分解
    WebSnapr-生成你的网站缩略图
    Lost HTML Intellisense within ASP.NET AJAX Controls
    调整调出输入法的顺序
    儿童网址大全
    gridview列 数字、货币和日期 显示格式
  • 原文地址:https://www.cnblogs.com/tun117/p/4943679.html
Copyright © 2020-2023  润新知