版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
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;
}