码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 3001(状态压缩DP)

时间:2017-08-29 18:02:42      阅读:166      评论:0      收藏:0      [点我收藏+]

标签:using   include   txt   scanf   pac   div   new   ==   while   

题意:遍历所有的城市的最短路径,每个城市最多去两遍。将城市的状态用3进制表示。

状态转移方程为 dp[NewS][i]=min( dp[NewS][i],dp[S][j]+dis[i][j])

S表示遍历点的状态,i表示到达第i个城市。

在到第i个城市的时候看是否存在一个j城市的路径,然后再从j到i更短。

#include <algorithm>
#include <cstdio>
#include <cstring>

#define Max 1000001
#define MAXN 150000
#define MOD 100000000
#define rin freopen("in.txt","r",stdin)
#define rout freopen("1.out","w",stdout)
#define Del(a,b) memset(a,b,sizeof(a))
#define INF 0x1f1f1f1f
using namespace std;
typedef long long LL;
int edge[11][11];
int n, m;
int tri[] = { 0, 1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683, 59049 };
int dp[59050][11];
int dig[59050][11];
void Init() {

    Del(dp, INF);
    Del(edge, INF);
    for (int i = 1; i <= n; i++) {
        dp[tri[i]][i] = 0;
    }
}
void Solve() {
    int ans = INF;
    for (int S = 0; S < tri[n+1]; S++) {
        int flag = 1;
        for (int i = 1; i <= n; i++) {
            if (dig[S][i] == 0)
                flag = 0;
            if (dp[S][i] == INF)
                continue;
            for (int j = 1; j <= n; j++) {
                if (i == j)
                    continue;
                if (edge[i][j] == INF || dig[S][j] == 2)
                    continue;
                int NewS = S + tri[j];
                dp[NewS][j] = min(dp[NewS][j], dp[S][i] + edge[i][j]);
            }
        }
        if (flag) {
            for (int j = 1; j <= n; j++)
                ans = min(ans, dp[S][j]);
        }
    }
    if (ans == INF) {
        puts("-1");
    } else {
        printf("%d\n", ans);
    }
    return;
}
int main() {
    //rin;
    for (int i = 0; i < 59050; i++) {
        int t = i;
        for (int j = 1; j <= 10; j++) {
            dig[i][j] = t % 3;
            t /= 3;
            if (t == 0)
                break;
        }
    }
    while (scanf("%d%d", &n, &m) != EOF) {
        Init();
        for (int i = 0; i < m; i++) {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            if (c < edge[a][b])
                edge[a][b] = edge[b][a] = c;
        }
        Solve();
    }
    return 0;
}

 

HDU 3001(状态压缩DP)

标签:using   include   txt   scanf   pac   div   new   ==   while   

原文地址:http://www.cnblogs.com/Belleaholic/p/7449416.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!