HDU 2437 Jerboas (剪枝搜索)

来源:互联网 发布:求网络兼职 编辑:程序博客网 时间:2024/04/29 03:54

题意:给定一幅图,图上有两种点T,P.......一只跳鼠在一个T点作为起始点,它想通过图上的路到达某个P点,P点满足如下要求:

(1).到达P点的途中路径权值为k的倍数

(2).尽量让路径权值取最小

(3).权值相同时,P点取更小的


此题一波三折,一开始反向建图,以为记忆化搜索能过.....TLE了,以为是枚举了是P的点浪费了时间;然后正向建图,从起点开始,也是TLE了,然后发现此题记忆化搜索影响不大,于是剪枝 v < vis[e][v % k] 的值才能继续搜索........剪枝完秒过,看来是卡剪枝的题目.......

#include <cstdio>#include <cmath>#include <iostream>#include <cstring># define MAX 1111# define INF 0x7FFFFFFFusing namespace std;char a[MAX];struct node {    int s,e,v,next;} ed[22222];int head[MAX],num = 0,n,m,k,st;int dp[MAX],vis[MAX][MAX]; //利用整数倍关系,剪枝void add(int s,int e,int v) {    ed[num].s = s;    ed[num].e = e;    ed[num].v = v;    ed[num].next = head[s];    head[s] = num++;}void init() {    memset(vis,0,sizeof(vis));    memset(head,-1,sizeof(head));    num = 0;}int dfs(int v0,int u0,int cur) {    if(a[v0 - 1] == 'P' && cur % k == 0) return dp[v0] = min(dp[v0],cur);    if(dp[v0] != INF) return dp[v0];    for(int i = head[v0]; i != -1; i = ed[i].next) {        int e = ed[i].e;        int v = ed[i].v + cur;        if(vis[e][v%k] == 0 || v < vis[e][v % k]) {            vis[e][v%k] = v;            dfs(e,u0,v);                    }    }}int main() {    int T;    cin >> T;    int casee = 1;    while(T --) {        init();        cin >> n >> m >> st >> k;        for(int i=1; i<=n; i++)             dp[i] = INF;        getchar();        int aa,bb,cc;        scanf("%s",a);        for(int i=1; i<=m; i++) {            scanf("%d%d%d",&aa,&bb,&cc);            add(aa,bb,cc);        }        printf("Case %d: ",casee++);        dfs(st,st,0);        int flag = 0,ind,ans = INF;        for(int i=1; i<=n; i++) {            if(dp[i] != INF) {                flag = 1;                if(ans > dp[i]) {                    ans = dp[i];                    ind = i;                }            }        }        if(flag) printf("%d %d\n",ans,ind);        else printf("-1 -1\n");    }    return 0;}


原创粉丝点击