HDU 4284 Travel (Folyd预处理+dfs暴搜)

题意:给你一些N个点,M条边,走每条边要花费金钱,然后给出其中必须访问的点,在这些点可以打工,但是需要先拿到证书,只可以打一次,也可以选择不打工之直接经过它。一个人从1号点出发,给出初始金钱,问你能不能访问所以的点,并且获得所以证书。

题解:目标是那些一定要访问的点,怎么到达的我们不关心,但是我们关系花费最少的路径,而且到达那个点后是一定要打工的,如果只是经过,那么在求花费最少的路径的时候已经考虑过了。

因此先用Folyd求出各个点直接的最短路径,由于N很小,又只要求出一个解,所以直接dfs暴搜就行了。

M很大,可能有重边。注意处理。

当时一看,图论题,没仔细想就跳过了。下面的代码加了输入挂,因为第一遍写T了,以为是输入问题,所以加上了。改了我好几个小时没过,重写一遍就过了。

#define HDU

#ifndef HDU

#include<bits/stdc++.h>

#else

//pragma comment(linker, "/STACK:1024000000,1024000000")

#include<cstdio>

#include<cstring>

#include<cmath>

#include<vector>

#include<map>

#include<set>

#include<algorithm>

//#include<iostream>

#endif // HDU

#define mins(s,x) if((x)<(s)) s = x

#define maxs(s,x) if((x)>(s)) s = x

using namespace std;

typedef long double ld;

typedef long long ll;





const int maxn = 105;

const int maxh = 20;

const int INF = 0x3f3f3f3f;



int N,M,Mon,H;

int dis[maxn][maxn];

inline void scan_d(int &ret)

{

    char c;ret=0;

    while((c=getchar())<'0'||c>'9');

    while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();

}



struct City

{

    int cost,earn,id;

    void input(){

        scanf("%d%d%d",&id,&earn,&cost);

    }

}city[maxh];





bool vis[maxh];







bool dfs(int u,int money,int cnt)

{

    if( cnt == H && money >= dis[u][1] )return true;

    for(int i = 0; i < H; i++) if(!vis[i]){

        int v = city[i].id;

        if( money >= dis[u][v]+city[i].cost ){

            vis[i] = 1;

            if(dfs(v,money-dis[u][v]-city[i].cost+city[i].earn,cnt+1)) return true;

            vis[i] = 0;

        }

    }

    return false;

}



void init()

{

    memset(vis,false,sizeof(vis));

    memset(dis,0x3f,sizeof(dis));

    for(int i = 1; i <= N; i++)

        dis[i][i]= 0;

}



//#define local



int main()

{

#ifdef local

    freopen("in.txt","r",stdin);

   // freopen("myout.txt","w",stdout);

#endif // local

    int T;

    scan_d(T);

    //scanf("%d",&T);

    while(T--){

        scan_d(N);scan_d(M);scan_d(Mon);

        //scanf("%d%d%d",&N,&M,&Mon);

        init();

        for(int i = 0; i < M; i++){

            int u,v,w;

            scan_d(u);scan_d(v);scan_d(w);

            //scanf("%d%d%d",&u,&v,&w);

            //if(u == v) continue;

            if(dis[u][v]>w) {

                dis[u][v] = w;

                dis[v][u] = dis[u][v];

            }



        }



        for(int k = 1; k <= N; k++)

            for(int i = 1; i <= N; i++){

                if(dis[i][k]<INF)

                for(int j = 1; j <= N; j++) {

                    mins(dis[i][j],dis[i][k]+dis[k][j]);

                }

            }



        scanf("%d",&H);

        for(int i = 0; i < H; i++){

            city[i].input();

        }



        printf("%s\n",dfs(1,Mon,0)?"YES":"NO");

    }



    return 0;

}

 

你可能感兴趣的:(HDU)