PAT甲级_1030 Travel Plan (30 分)|1031 Hello World for U (20 分)|1032 Sharing (25 分)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_44705116/article/details/102646423

1、1030 Travel Plan (30 分)

题目大意:找出最短路径。再从最短路径中,找出花费最少的路径;

首先使用Dijkstra算法得到最短路径,使用pre保存最短路径中各点的前驱,再使用DFS对各条路径的总花费进行比较,得出花费最少的最短路径。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int INF = 99999999;

int N, M, S, D;

vector<int> temppath, path, pre[509];
int cost[509][509], dis[509][509], mincost=INF;
bool visit[509];
int d[509];

void DFS(int x) {
	temppath.push_back(x);
	if (x == S) {
		int sumcost = 0;
		for (int i = 0; i < temppath.size() - 1; i++) {
			int id = temppath[i], next = temppath[i + 1];
			sumcost += cost[id][next];
		}
		if (sumcost < mincost) {
			mincost = sumcost;
			path = temppath;
		}
		temppath.pop_back();
		return;
	}
	for (int i = 0; i < pre[x].size(); i++) {
		DFS(pre[x][i]);
	}
	temppath.pop_back();
}

int main() {
	fill(dis[0], dis[0] + 509 * 509, INF);
	fill(d, d + 509, INF);
	scanf("%d%d%d%d", &N, &M, &S, &D);
	int distance, fee, u, v;
	for (int i = 0; i < M; i++) {
		scanf("%d%d%d%d", &u, &v, &distance, &fee);
		dis[u][v] = dis[v][u] = distance;
		cost[u][v] = cost[v][u] = fee;
	}
	pre[S].push_back(S);
	d[S] = 0;
	for (int k = 0; k < N; k++) {
		int j = -1, mindis = INF;
		for (int i = 0; i < N; i++) {
			if (visit[i] == false && d[i] < mindis) {
				mindis = d[i];
				j = i;
			}
		}
		if (j == -1) break;
		visit[j] = true;
		for (int p = 0; p < N; p++) {
			if (visit[p] == false && dis[p][j] != INF) {
				if (d[p] > d[j] + dis[p][j]) {
					d[p] = d[j] + dis[p][j];
					pre[p].clear();
					pre[p].push_back(j);
				}
				else if (d[p] == d[j] + dis[p][j]) {
					pre[p].push_back(j);
				}
			}
		}
	}
	DFS(D);
	for (int i = path.size() - 1; i >= 0; i--) {
		if (i != path.size() - 1) printf(" ");
		printf("%d", path[i]);
	}
	printf(" %d %d", d[D], mincost);
	return 0;
}

2、1031 Hello World for U (20 分)

将u两个交叉处的字符计算上。得到n=n1+n2+n1+2;为将n1最大化,n1=n/3,n2=n/3+n%3;用一个二维数组储存要输出的字符串。

#include<cstdio>
#include<iostream>
#include<string.h>
using namespace std;

int main() {
	int space[30][30];
	char s[90];
	scanf("%s", &s);
	memset(space, ' ', sizeof(space));
	int n1 = (strlen(s) + 2) / 3, n2 = (strlen(s) + 2) / 3 + (strlen(s) + 2) % 3;
	int index = 0;
	for (int i = 0; i < n1; i++) {
		space[i][0] = s[index++];
	}
	for (int i = 1; i <= n2-2; i++) {
		space[n1-1][i] = s[index++];
	}
	for (int i = n1-1; i >= 0; i--) {
		space[i][n2 - 1] = s[index++];
	}
	for (int i = 0; i < n1; i++) {
		for (int j = 0; j < n2; j++) {
			printf("%c", space[i][j]);
		}
		printf("\n");
	}
}

3、1032 Sharing (25 分)

题目大意:给出两个链表,输出两个链表交叉的点。

输入后,遍历第一个链表。将遍历之后的节点作标记,随后遍历第二个链表,遍历到做过标记的节点,则输出该节点编号。

#include<iostream>
#include<algorithm>
using namespace std;
int n;
struct word{
    int next;
    char c;
    bool flag;
}rua[100000];

int main(){
    int a, b, x, z;
    char y;
    scanf("%d%d%d", &a, &b, &n);    
    for(int i=0;i<n;i++){
        scanf("%d %c %d",&x, &y, &z);
        rua[x]={z, y, false};
    }
    for(int i=a;i!=-1;i=rua[i].next){
        rua[i].flag=true;
    }
    for(int i=b;i!=-1;i=rua[i].next){
        if(rua[i].flag==true) {printf("%05d", i);
            return 0;
        }
    }
    printf("-1");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44705116/article/details/102646423
今日推荐