HDU 3001(状压dp 三进制)

题目注意: 每个点可以经过不超过两次,所以把二进制转换成三进制,就可以很好的存储状态。

dp【i】【j】表示在j状态下,最后一次位置在i点。


还是比较好理解的一个状压dp

#include <iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<queue>

using namespace std;
const int maxn=15;
int ege[maxn][maxn];
int dp[maxn][60000];
int in[maxn];
int vis[maxn];
int n,m;
int get(int x)
{
    int num = 0;
    for(int i=0; i<n;i++)
    {
        vis[i] = x%3;
        x /= 3;
        if(vis[i])
            num++;
    }
    return num;
}
int main()
{
    in[0] = 1;
    for(int i=1; i<=10; i++)
    {
        in[i] = in[i-1]*3;
    }
    while(cin>>n>>m)
    {
        int ans = 0;
        int have_find = 0;
        memset(dp,-1,sizeof(dp));
        memset(ege,-1,sizeof(ege));
        while(m--)
        {
            int a,b,c;
            cin>>a>>b>>c;
            ans += c;
            a--;
            b--;
            if(ege[a][b] == -1)
            {
                ege[a][b] = c;
                ege[b][a] = c;
            }
            else
            {
                ege[a][b] = min(ege[a][b],c);
                ege[b][a] = min(ege[b][a],c);
            }
        }

        ans*=2;
        for(int i=1; i<in[n]; i++)
        {
            int num = get(i);
            for(int j=0; j<n; j++)
            {
                if(vis[j])
                {

                    if(num == 1)
                    {
                        dp[j][i] = 0;
                    }
                    if(dp[j][i]== -1)
                        continue;
                    if(num == n)
                    {
                        ans = min(ans, dp[j][i]);
                        have_find = 1;
                        continue;
                    }
                    for(int k = 0; k < n; k++)
                    {
                        //cout<<"now i="<<i<<" j="<<j<<" k="<<k<<" vis[k]="<<vis[k]<<endl;
                        if(k!=j && vis[k]<2 && ege[k][j]!=-1)
                        {
                            int now = i + in[k];
                            if(dp[k][now] != -1)
                               dp[k][now] = min(dp[k][now],dp[j][i]+ ege[k][j]);
                            else
                                dp[k][now] = dp[j][i]+ ege[k][j];
                        }
                    }
                }
            }
        }
       // cout<<dp[0][1]<<endl;
       // cout<<dp[1][4]<<endl;
        if(have_find == 0)
            cout<<-1<<endl;
        else
            cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sinat_36215255/article/details/80909971