首页 > 代码库 > XYZZY UVA 10557 (接近于有向图的最长路问题)
XYZZY UVA 10557 (接近于有向图的最长路问题)
说说:
这道题相对来说,感觉难度稍大一点,因为有好几个点到后来才想到。首先题目给你一系列的节点,序号从1到n,并且告诉你每个节点可以进入的下一个节点的序号。假设开始你有能量值100,现在要求你从节点1开始,不断地从一个节点进入另一个节点,当然进入的时候你的能量值要加上节点代表的数值(范围是-100到+100)。并且你可以重复进入同一个节点多次。当你的能力值小于等于0时,你就失败了。问你有没有办法能从节点1走到节点n。下面来说一说解题方法:首先最令人感到痛苦的是,一个节点可以重复经过,这样的话,如果不断DFS很可能死循环出不来了。所以我就设了一个数组,标记第一次进入某个节点时,此时的能量值。但是后来仔细一想,其实不一定要走到最后一个节点n,只要能够重复到达一个节点,并且之后的能量值比后来要大,那么必然是能成功到达最终节点的。不过这个想法其实是错误的,因为这是一个单向图,很有可能在一个圈子里绕,然后就出不来了。所以有必要判断一下每个节点在不管能量值的情况下,能否到达最终节点。在这次的题解报告中,我其实用的方法比较笨啦,就是把每个节点DFS一遍,其实只要从最终节点逆DFS一下,碰到个节点做一下标记也是OK的。根据以上的分析,我们就可以从节点1开始DFS了,其中当再次到达一个节点,并且当到达一个到不了最终节点的节点或者再次到达一个节点,且此次的能量值小于等于第一次到的能量值,则停此节点停止DFS。最后当再次到达一个节点,且能量值大于第一次,该节点也可以到达最终节点,那么整个遍历都是成功的。(省略了明显的成功或失败的情况)详细的解题步骤,请阅读下面的源代码。
源代码:
#include <stdio.h> #include <string.h> #define MAXN 100+5 int room[MAXN];//每个节点的能量值 int roomconnect[MAXN][MAXN];//该节点可以到达的节点且第一个元素为可到达的节点个数 int roomenergy[MAXN];//第一次到达某节点的能量值 int roomvisit[MAXN];//dfs标记 char abletofinish[MAXN];//该节点能否到达最终节点 int energy; int n; int edfs(int);//考虑能量值 int dfs(int);//判断某节点能否到最终节点,不考虑能量值 int main(){ int i,j; // freopen("data","r",stdin); while(scanf("%d",&n)&&n!=-1){ energy=100; for(i=1;i<=n;i++){ scanf("%d",&room[i]); scanf("%d",&roomconnect[i][0]); for(j=1;j<=roomconnect[i][0];j++) scanf("%d",&roomconnect[i][j]); } for(i=1;i<=n;i++){ roomenergy[i]=-1; memset(roomvisit,0,sizeof(roomvisit)); abletofinish[i]=dfs(i);//判断每个节点能否到达最终节点,不考虑能量值 } if(edfs(1)) printf("winnable\n"); else printf("hopeless\n"); } return 0; } int edfs(int num){ int i; energy+=room[num]; if(!abletofinish[num]){//该节点不能到达最终节点 energy-=room[num];//注意回溯 return 0; } else if(energy<=roomenergy[num]||energy<=0){//再次到达某节点,且能量值小于等于第一次的值,则不再深搜 energy-=room[num]; return 0; } else if(num==n&&energy>0||roomenergy[num]!=-1&&energy>roomenergy[num]){//再次到达某节点,且能量值大于第一次,且该节点能到最终节点,则成功 energy-=room[num]; return 1; } roomenergy[num]=energy; for(i=1;i<=roomconnect[num][0];i++) if(edfs(roomconnect[num][i])){ energy-=room[num]; return 1; } return 0; } int dfs(int num){ int i; if(num==n) return 1; roomvisit[num]=1; for(i=1;i<=roomconnect[num][0];i++) if(!roomvisit[roomconnect[num][i]]) if(dfs(roomconnect[num][i])) return 1; return 0; }
XYZZY UVA 10557 (接近于有向图的最长路问题)