HDU 4284 状压DP

HDU 4284
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4284
题意:
给一个图,n个点m条边,边有权值代表在两边通行的代价。
给定H个城市,每个城市有入门费Ci,入门后有Di收入。
现要求从城市1出发,最后也要返回城市1,H个城市均要遍历到,问能否全部遍历到。
思路:
状压DP。dp[i][j],i表示状态,j表示最后一次到达的位置。

比赛的时候一直在想网络流,还是图论不熟练啊~
源码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
#define inf (1000000000)
const int MAXN = 17;
int dp[1 << MAXN][MAXN];
int gra[105][105];
struct D
{
    int u;
    int c1, c2;
}d[MAXN];
void floyd(int n)
{
    for(int k = 1 ; k <= n ; k++){
        for(int i = 1 ; i <= n ; i++){
            for(int j = 1 ; j <= n ; j++)
                gra[i][j] = min(gra[i][j], gra[i][k] + gra[k][j]);
        }
    }
    for(int i = 1 ; i <= n ; i++)
        gra[i][i] = 0;
}
void DP(int num, int M)
{
    memset(dp, -1, sizeof(dp));
    for(int i = 0 ; i < num ; i++){
        if(M >= d[i].c1 + gra[1][d[i].u]){
            dp[1 << i][i] = M - d[i].c1 - gra[1][d[i].u] + d[i].c2;
//            printf("i = %d, dp = %d\n", i, M - d[i].c1 - gra[1][d[i].u] + d[i].c2);
        }
    }
    for(int i = 0 ; i < (1 << num) ; i++){
        for(int j = 0 ; j < num ; j++){
            if(( (1 << j) & i) && dp[i][j] != -1){
//                printf("i = %d, j = %d\n", i, j);
                for(int k = 0 ; k < num ; k++){
                    if(!(i & (1 << k))){
                        int ts = (i | (1 << k));
                        int u1 = d[j].u, u2 = d[k].u;
                        if(dp[i][j] >= d[k].c1 + gra[u1][u2]){
                            dp[ts][k] = max(dp[ts][k], dp[i][j] - gra[u1][u2] - d[k].c1 + d[k].c2);
//                            printf("ts = %d, k = %d, dp = %d\n", ts, k, dp[ts][k]);
                        }
                    }
                }
            }
        }
    }
}
int main()
{
//    freopen("1007.in", "r", stdin);
    int n, m, M;
    int t;
    scanf("%d", &t);
    while(t--){
        scanf("%d%d%d", &n, &m, &M);
        for(int i = 1 ; i <= n ; i++){
            for(int j = 1 ; j <= n ; j++){
                gra[i][j] = inf;
                if(i == j)  gra[i][j] = 0;
            }
        }
        int u, v, w;
        for(int i = 0 ; i < m ; i++){
            scanf("%d%d%d", &u, &v, &w);
            gra[u][v] = min(gra[u][v], w);
            gra[v][u] = min(gra[v][u], w);
        }
        floyd(n);
        scanf("%d", &m);
        for(int i = 0 ; i < m ; i++)
            scanf("%d%d%d", &d[i].u, &d[i].c2, &d[i].c1);
        DP(m, M);
        int ans = -1;
        for(int i = 0 ; i < m ; i++){
            ans = max(ans, dp[(1 << m) - 1][i] - gra[1][d[i].u]);
//            printf("i = %d, dp = %d\n", i, dp[(1 << m) - 1][i]);
        }
        if(ans >= 0)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

你可能感兴趣的:(HDU 4284 状压DP)