图的深搜+回溯练习题:POJ2197

POJ 2197题意:
给定n个城市及其之间的距离,以及距离限制len 初始点s, 结束点e,
要求求出从s到e的所有不大于len的路径并输出,按照距离从小到大输出,如果距离相等,
就按照路径的字典升序输出。

样例:
Sample Input

4 5 4个顶点,5条边
1 2 2 顶点1到2之间的距离为2
1 3 3
1 4 1
2 3 2
3 4 4
1 3 //起点和终点
4 //距离限制

-1

Sample Output

Case 1:
3: 1 3
4: 1 2 3


思路:明显DFS+记录路径。


import java.util.*;
public class Main{
static final int INF=100000;
Point arr[];//记录符合条件所有解(终点)

int v,s,e,len;//顶点数,起点,终点,距离限定
int map[][];//城市的邻接矩阵
boolean f[];//深搜时记录顶点是否访问过
int x[];//用于记录从起点到终点的路径
int ii;//arr[]的下标,从0开始符合条件
static int counter = 0;

public Main(int v,int s,int e,int len,int[][] map){
this.v=v;//顶点数
this.s=s;//起点
this.e=e;//终点
this.len=len;//距离限定
this.map=map;//图的邻接矩阵
f =new boolean[v+1];
x=new int[v+1];
arr=new Point[4000];
for(int i=0;i<4000;i++)
arr[i]=new Point();
}

public static void main(String[] args){
Scanner in=new Scanner(System.in);
int v, r,s, e,len;//r:边的数目
int[][] map;
while(true)
{
v=in.nextInt();
if(v==-1) break;
r=in.nextInt();
map=new int[v+1][v+1];//邻接矩阵
for(int i=1;i<=v;i++)
{
for(int j=1;j<=v;j++)
{
map[i][j] = INF;
}
}
for(int i=0;i<r;i++)
{
int a,b,c;
a=in.nextInt();
b=in.nextInt();
c=in.nextInt();
map[a][b] = map[b][a] = c;//这是无向图
}
s=in.nextInt();
e=in.nextInt();
len=in.nextInt();
Main m=new Main(v,s,e,len,map);
m.go();
}
}


public void go(){

System.out. printf("Case %d:\n",++counter);
f[s] = true;
x[0] = s;//旅游的步骤,从0(起点)开始
ii = 0;
dfs(s,0,1);//旅游的步骤,第1步
if(ii==0) System.out.printf(" NO ACCEPTABLE TOURS\n");
else
{
Arrays.sort(arr ,0, ii ,new SampleComparator());
for(int i=0;i<ii;i++)
{
System.out.printf(" %d: ",arr[i].sum);
for(int j=0;j<arr[i].jj;j++)
{

System.out.printf("%d ",arr[i].num[j]);
}
System.out.println();
}
}
System.out.println();
}

//ind:旅游的步骤,从0(起点)开始,
//sum:旅游的距离
//cur:旅游的当前点
void dfs(int cur , int sum , int ind){
if( sum > len ) return ;
if( cur == e){//到达终点
arr[ii].sum = sum;//记录起点到终点的距离
for(int i=0;i<ind;i++)//记当起点到终点的路径
{
arr[ii].num[i] = x[i];
}
arr[ii++].jj = ind;//记录起点到终点经过的城市数
return ;
}
for(int i=1;i<=v;i++)//搜索当前点的所有邻接点
{
if( !f[i] && map[cur][i] < INF )//i没有访问过,且有路径可通。
{
if( sum + map[cur][i] <= len )//剪枝
{
f[i] = true;
x[ind++] = i;//记录路径
dfs(i , sum+map[cur][i],ind);//递归深搜
f[i] = false;//回溯
x[ind--] = 0;//回溯
}
}
}
}




}


class Point{
int jj;//从起点到此点经过的城市数目
int sum ;//从起点到此点的距离
int num[]=new int[25];//从起点到此点的路径
}

class SampleComparator implements Comparator<Point> {
public int compare(Point a, Point b) {
if( a.sum != b.sum ){
if(a.sum < b.sum) return -1;
else return 1;
}
else{
int len1 = a.jj;
int len2 = b.jj;

for(int i=0;i<Math.max(a.jj,b.jj);i++)
{
if( a.num[i] != b.num[i] ) {
if(a.num[i] < b.num[i]) return -1;
else return 1;
}
}
return 0;
}
}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值