andre_joy

导航

hdu 4284

地址:http://acm.hdu.edu.cn/showproblem.php?pid=4284

题意:给出一些城市,从1出发,旅游一圈回到1,由于花费可能不够,所以选择一些城市打工,打工之前需要花费d买一个证,工资为c。选中的城市必须去工作一次,而且只能工作一次,问能不能完成旅行

mark:先用floyd预处理,记住一定要把断点放在最外层循环!!!状态压缩dp。

代码:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <map>

using namespace std;

const int INF = (1 << 28);
int n,m,mon,h;
int adj[110][110], s[20], c[20], d[20];
int dp[1 << 16][20];

void init()      //Floyd预处理。!!!找了一小时啊,断点一定要放在最外层循环! 
{
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            for(int k = 0; k < n; k++)
                if(i != j && i != k && j != k)
                    adj[j][k] = min(adj[j][k], adj[j][i]+adj[i][k]);
}

bool find()
{
    for(int i = 0; i < h; i++)
        if(dp[(1 << h)-1][i] >= adj[s[i]][0]) return 1;
    return 0;
}

int main()
{
    int t;
    int i,j,k;
    int aa,bb,cc;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d%d", &n, &m, &mon);
        for(i = 0; i < n; i++)
            for(j = 0; j < n; j++)
            {
                if(i == j) adj[i][i] = 0;
                else adj[i][j] = INF;
            }
        for(i = 0; i < m; i++)
        {
            scanf("%d%d%d", &aa, &bb, &cc);
            aa--,bb--;
            adj[aa][bb] = min(adj[aa][bb], cc);
            adj[bb][aa] = adj[aa][bb];
        }
        init();
        scanf("%d", &h);
        int f = -1;
        for(i = 0; i < h; i++)
        {
            scanf("%d%d%d", s+i, c+i, d+i);
            s[i]--;
            if(s[i] == 0) f = i;
        }
        memset(dp, -1, sizeof(dp));
        if(f == -1)   //加一个空点,当作起始点。 
        {
            s[h] = c[h] = d[h] = 0;
            f = h++;
        }
        if(mon >= d[f]) dp[1 << f][f] = mon-d[f]+c[f];
        dp[0][f] = mon;
        for(i = 0; i < (1 << h); i++)
            for(j = 0; j < h; j++)
            {
                if(dp[i][j] == -1) continue;
                for(k = 0; k < h; k++)
                {
                    if(i & (1 << k)) continue;
                    if(dp[i][j] >= adj[s[j]][s[k]]+d[k])
                        dp[i|(1<<k)][k] = max(dp[i|(1<<k)][k], dp[i][j]-adj[s[j]][s[k]]-d[k]+c[k]);
                }
            }
        puts(find() ? "YES" : "NO");
    } 
    return 0;
}

posted on 2012-09-12 16:44  andre_joy  阅读(93)  评论(0编辑  收藏  举报