PAT 1030. Travel Plan

这个题做了一个下午,刚开始用Java写,

<span style="font-size:14px;">import java.util.*;

public class Main {
	
	
	static int INF = 99999999;
	
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		int N = sc.nextInt();
		int M = sc.nextInt();
		int start = sc.nextInt();
		int end   = sc.nextInt();
		
		int[][] d = new int[N][N];
		int[][] c = new int[N][N];
		for(int i=0; i<N; i++)
			for(int j=0; j<N; j++) {
				d[i][j] = INF;
				c[i][j] = INF;
			}
		
		for(int i=0; i<M; i++) {
			int c1 = sc.nextInt();
			int c2 = sc.nextInt();
			int d1  = sc.nextInt();
			int cc = sc.nextInt();
			d[c1][c2] = d1;
			d[c2][c1] = d1;
			c[c1][c2] = cc;
			c[c2][c1] = cc;
		}
		
		
		boolean[] marked = new boolean[N];
		int[] dist = new int[N];
		for(int i=0; i<N; i++)
			dist[i] = d[start][i];
		int[] cost = new int[N];
		for(int i=0; i<N; i++)
			cost[i] = c[start][i];
		
		int[] prev = new int[N];
		
		marked[start] = true;
		dist[start] = 0;
		cost[start] = 0;
		
		int newP = start;
		while(newP != end) {
			
			for(int i=0; i<N; i++) {
				if(!marked[i] && d[newP][i] < INF) {
					if(dist[newP] + d[newP][i] < dist[i]) {
						dist[i] = dist[newP] + d[newP][i];
						cost[i] = cost[newP] + c[newP][i];
						prev[i] = newP;
					} else if(dist[newP] + d[newP][i] == dist[i]) {
						if(cost[newP] + c[newP][i] < cost[i]) {
							cost[i] = cost[newP] + c[newP][i];
							prev[i] = newP; 
						}
					}
				}
			}
			
			int min = INF;
			for(int i=0; i<N; i++) {
				if(!marked[i] && dist[i] < min) {
					min = dist[i];
					newP = i;
				}
			}
			
			marked[newP] = true;
		}
		
		StringBuilder sb = new StringBuilder();
		int t = end;
		while(t != start) {
			sb.insert(0, t + " ");
			t = prev[t];
		}
		sb.insert(0, start + " ");
		sb.append(dist[end]);
		sb.append(" " + cost[end]); 
		
		System.out.println(sb);
	}
}</span><span style="font-size:24px;">
</span>

提示内存超了,改用C++写,还是超了,然后参考了别人的博客,PAT 1030. Travel Plan (30) (最短路),算法思路都差不多,但是它可以AC,好吧,那我就一点一点的改成你的样子,然而几个小时之后终于在它的输出上看出来了问题所在。。。。


输出我写的循环条件是
<span style="font-size: 14px;">while(t != start)</span>

而实际上在Dijkstra初始化时

<span style="font-size: 14px;"><span style="font-size:24px;">marked[start] = true;</span></span>
所以在第一次循环的时候下面的语句是不会被执行的

<span style="font-size: 14px;"><span style="font-size:24px;"><span style="font-size:24px;">prev[i] = newP;</span></span></span>

所以造成的结果是一直在死循环,一直往StringBuilder中append数据,所以最终要么超时,要么内存超限。但是也不能用默认赋值的0,因为节点就是从0开始的,可能会导致提前退出循环。

修改了之后,终于AC。。。。

<span style="font-size:14px;">package p1030;

import java.util.*;

public class Main {
	
	
	static int INF = 99999999;
	
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		int N = sc.nextInt();
		int M = sc.nextInt();
		int start = sc.nextInt();
		int end   = sc.nextInt();
		
		int[] prev = new int[N];
		int[][] d = new int[N][N];
		int[][] c = new int[N][N];
		for(int i=0; i<N; i++) {
			prev[i] = -1;
			for(int j=0; j<N; j++) {
				d[i][j] = INF;
				c[i][j] = INF;
			}
		}
		
		for(int i=0; i<M; i++) {
			int c1 = sc.nextInt();
			int c2 = sc.nextInt();
			int d1  = sc.nextInt();
			int cc = sc.nextInt();
			d[c1][c2] = d1;
			d[c2][c1] = d1;
			c[c1][c2] = cc;
			c[c2][c1] = cc;
		}
		
		
		boolean[] marked = new boolean[N];
		int[] dist = new int[N];
		for(int i=0; i<N; i++)
			dist[i] = d[start][i];
		int[] cost = new int[N];
		for(int i=0; i<N; i++)
			cost[i] = c[start][i];
		
		marked[start] = true;
		dist[start] = 0;
		cost[start] = 0;
		
		int newP = start;
		while(newP != end) {
			
			for(int i=0; i<N; i++) {
				if(!marked[i] && d[newP][i] < INF) {
					if(dist[newP] + d[newP][i] < dist[i]) {
						dist[i] = dist[newP] + d[newP][i];
						cost[i] = cost[newP] + c[newP][i];
						prev[i] = newP;
					} else if(dist[newP] + d[newP][i] == dist[i]) {
						if(cost[newP] + c[newP][i] < cost[i]) {
							cost[i] = cost[newP] + c[newP][i];
							prev[i] = newP; 
						}
					}
				}
			}
			
			int min = INF;
			for(int i=0; i<N; i++) {
				if(!marked[i] && dist[i] < min) {
					min = dist[i];
					newP = i;
				}
			}
			
			marked[newP] = true;
		}
		
		StringBuilder sb = new StringBuilder();
		int t = end;
		while(t != -1) {
			sb.insert(0, t + " ");
			t = prev[t];
		}
		sb.insert(0, start + " ");
		sb.append(dist[end]);
		sb.append(" " + cost[end]); 
		
		System.out.println(sb);
	}
}
</span>


另外在附上C++代码

#include <cstdio>
#include <cstdlib>
#include <vector>
#include <stack>

using namespace std;
const int MAX = 501;
const int INF = 999999999;

int N, M, start, t, c1, c2, d1, cc, i, j;
int d[MAX][MAX], c[MAX][MAX];
int marked[MAX];
int dist[MAX], cost[MAX], pre[MAX];

vector<int> v;
stack<int> path;

int main()
{
    //for(int i=0; i<MAX; i++)
        //printf("%d ", &marked[i]);

    scanf("%d %d %d %d", &N, &M, &start, &t);

    for(i=0; i<N; i++) {
        //marked[i] = 0;
        pre[i] = -1;
        for(j=0; j<N; j++) {
            d[i][j] = INF;
            c[i][j] = INF;
        }
    }

    for(i=0; i<M; i++) {
        scanf("%d %d %d %d", &c1, &c2, &d1, &cc);
        d[c1][c2] = d1;
        d[c2][c1] = d1;
        c[c1][c2] = cc;
        c[c2][c1] = cc;
    }

    for(i=0; i<N; i++) {
        dist[i] = d[start][i];
        cost[i] = c[start][i];
    }

    marked[start] = 1;
    dist[start] = 0;
    cost[start] = 0;

    int newP = start;
    while(newP != t) {

        for(i=0; i<N; i++) {
            if(marked[i] == 0 && d[newP][i] < INF) {
                if(dist[newP] + d[newP][i] < dist[i]) {
                    dist[i] = dist[newP] + d[newP][i];
                    cost[i] = cost[newP] + c[newP][i];
                    pre[i] = newP;
                } else if(dist[newP] + d[newP][i] == dist[i]) {
                    if(cost[newP] + c[newP][i] < cost[i]) {
                        cost[i] = cost[newP] + c[newP][i];
                        pre[i] = newP;
                    }
                }
            }
        }

        int min_dist = INF;
        for(i=0; i<N; i++) {
            if(marked[i] == 0 && dist[i] < min_dist) {
                min_dist = dist[i];
                newP = i;
            }
        }

        marked[newP] = 1;
    }

    int p = pre[t];
    while(p!=-1){
        path.push(p);
        p = pre[p];
    }

    printf("%d",start);
    while(!path.empty()){
        printf(" %d",path.top());
        path.pop();
    }
    printf(" %d",t);

    printf(" %d %d\n",dist[t],cost[t]);

}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值