HDU2437 Jerboas 深度优先遍历 + 剪枝

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2437

参考博文:http://blog.csdn.net/u013167299/article/details/47358245

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
#define N 1005
//对应题目的n、m、s、k 
int n,m,s,k;
//对应洞穴的类型 
char kinds[N];
//node 图节点类型 
struct node{
    int to,len;
};
//
vector< vector<node> > G;
//用于剪枝 
int mod[N][N];

//ans 存放结果
//destination 记录目的地 
long long ans;
int destination;

//深度优先遍历
//n当前所在节点
//sum 当前走过的路径长度 
void dfs(int n,long long sum){
    //如果sum不是初始值,并且当前走过的路径长度sum 小于 ans 
    if(ans!=-1&&sum>ans)
        return;
    //判断洞穴类型以及路径长度是否符合要求 
    if(kinds[n]=='P'&&sum%k==0){
        if(ans==-1||ans>sum){
            ans=sum;
            destination=n;
        }else if(ans==sum&&destination>n)
            destination=n;
        return;
    }
    
    //以n为基点,遍历其邻接点 
    int max=G[n].size();
    for(int i=0;i<max;i++){
        int to=G[n][i].to;
        int dis=sum+G[n][i].len;
        //如果多次到达一个顶点的话,而且余数又相同,那么保留距离小的
        if(mod[to][dis%k]!=-1&&mod[to][dis%k]<=dis)
            continue;
        mod[to][dis%k]=dis;
        dfs(to,dis);
    }
}
int main(){
    int T;
    cin>>T;
    for(int t=1;t<=T;t++){
        cin>>n>>m>>s>>k;
        for(int i=1;i<=n;i++)
            cin>>kinds[i];
        //重置图等相关数据    
        ans=-1;
        destination=-1;
        G.clear();
        G.resize(n+2);
        memset(mod,-1,sizeof(mod));
        int x;
        node p;
        for(int i=1;i<=m;i++){
            cin>>x>>p.to>>p.len;
            G[x].push_back(p);
        }
        dfs(s,0);
        cout<<"Case "<<t<<": "<<ans<<" "<<destination<<endl;
    }
    return 0;
}

 

posted @ 2017-03-26 15:34  茄阁云云  阅读(292)  评论(0编辑  收藏  举报