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
",dfs(1,Mon,0)?"YES":"NO");
    }

    return 0;
}
原文地址:https://www.cnblogs.com/jerryRey/p/4665683.html