您的位置:首页 > 其它

Hdu 4284 Travel(状态压缩)

2014-11-07 21:01 239 查看


Travel

Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 3161 Accepted Submission(s): 842



Problem Description

  PP loves travel. Her dream is to travel around country A which consists of N cities and M roads connecting them. PP has measured the money each road costs. But she still has one more problem: she doesn't have enough money. So she must work during her travel.
She has chosen some cities that she must visit and stay to work. In City_i she can do some work to earn Ci money, but before that she has to pay Di money to get the work license. She can't work in that city if she doesn't get the license but she can go through
the city without license. In each chosen city, PP can only earn money and get license once. In other cities, she will not earn or pay money so that you can consider Ci=Di=0. Please help her make a plan to visit all chosen cities and get license in all of them
under all rules above.

  PP lives in city 1, and she will start her journey from city 1. and end her journey at city 1 too.



Input

  The first line of input consists of one integer T which means T cases will follow.

  Then follows T cases, each of which begins with three integers: the number of cities N (N <= 100) , number of roads M (M <= 5000) and her initiative money Money (Money <= 10^5) .

  Then follows M lines. Each contains three integers u, v, w, which means there is a road between city u and city v and the cost is w. u and v are between 1 and N (inclusive), w <= 10^5.

  Then follows a integer H (H <= 15) , which is the number of chosen cities.

  Then follows H lines. Each contains three integers Num, Ci, Di, which means the i_th chosen city number and Ci, Di described above.(Ci, Di <= 10^5)



Output

  If PP can visit all chosen cities and get all licenses, output "YES", otherwise output "NO".



Sample Input

2
4 5 10
1 2 1
2 3 2
1 3 2
1 4 1
3 4 2
3
1 8 5
2 5 2
3 10 1
2 1 100
1 2 10000
1
2 100000 1




Sample Output

YES
NO




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

题解:
先floyed出两个城市间最小的费用,用dp[i][j]保存当前i状态下到达j城市的最小费用。

AC CODE:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<set>
#include<queue>
#include<stack>
#include<vector>
#include<map>

#define N 110
#define Mod 10000007
#define lson l,mid,idx<<1
#define rson mid+1,r,idx<<1|1
#define lc idx<<1
#define rc idx<<1|1
const double EPS = 1e-11;
const double PI = acos ( -1.0 );
const double E = 2.718281828;
typedef long long ll;

const int INF = 1000010;

using namespace std;

int  n, m, money, num;
int mp

;///记录两个城市间的最小费用
int dp[ ( 1 << 15 ) + 1][17];///以i状态到达j城市的最小花费

struct jobs
{
    int city;
    int c, d;
} H[17];

void floyed() ///两城市之间最小费用
{
    for ( int k = 1; k <= n; k++ )
        for ( int i = 1; i <= n; i++ )
            for ( int  j = 1; j <= n; j++ )
            {
                if ( mp[i][j] > mp[i][k] + mp[k][j] )
                    mp[i][j] = mp[i][k] + mp[k][j];
            }
}

int DP()
{
    for ( int i = 0; i < ( 1 << num ); i++ )
    {
        for ( int j = 0; j < num; j++ )
        {
            if ( dp[i][j] == INF )
                continue;
            for ( int k = 0; k < num; k++ )
            {
                if ( ( ( 1 << k ) &i ) || ( k == j ) ) ///第k座城市已选
                    continue;
                if ( money - dp[i][j] - mp[H[j].city][H[k].city] < H[k].d ) ///剩下的钱不够买license
                    continue;
                dp[i | ( 1 << k )][k] = min ( dp[i | ( 1 << k )][k], dp[i][j] + mp[H[j].city][H[k].city] + H[k].d - H[k].c );
            }
        }
    }
    int x = ( 1 << num ) - 1;
    for ( int i = 0; i < num; i++ )
        if ( dp[x][i] + mp[H[i].city][1] <= money ) ///最后一座城市回到第一座城市
            return 1;
    return 0;
}

int main()
{
    //freopen("in.txt","r",stdin);
    int t;
    cin >> t;
    while ( t-- )
    {
        scanf ( "%d %d %d", &n, &m, &money );
        int x, y, z;
        for ( int i = 0; i <= n; i++ )
            for ( int j = 0; j <= i; j++ )
            {
                if ( j == i )
                    mp[i][j] = 0;
                else
                    mp[i][j] = mp[j][i] = INF;
            }
        for ( int i = 0; i < m; i++ )
        {
            scanf ( "%d%d%d", &x, &y, &z );
            if ( mp[x][y] > z )
                mp[x][y] = mp[y][x] = z;
        }
        floyed();
        scanf ( "%d", &num );
        for ( int i = 0; i < ( 1 << num ); i++ )
            for ( int j = 0; j < num; j++ )
                dp[i][j] = INF;
        for ( int i = 0; i < num; i++ )
        {
            scanf ( "%d %d %d", &H[i].city, &H[i].c, &H[i].d );
            if ( money >= mp[1][H[i].city] + H[i].d )
                dp[1 << i][i] = mp[1][H[i].city] - H[i].c + H[i].d;
        }
        if ( DP() )
            cout << "YES\n";
        else cout << "NO\n";
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: