1001 A+B Format (20分)
import java.io.*;
import java.util.*;
class Main{
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken()), b = Integer.parseInt(st.nextToken());
int sum = a + b, abs = Math.abs(sum);
LinkedList<String> res = new LinkedList<>();
int count = 0; //已经插入的位数
while(abs != 0){
int digit = abs % 10;
res.add(0, Integer.toString(digit)); //每次将当前最低位插入链表的头部
count++;
if(count % 3 == 0 && abs >= 10){ //abs >= 10保证之后仍有数字插入
res.add(0, ",");
}
abs /= 10;
}
if(res.size() == 0) //没有插入数字,说明两数之和为0
res.add("0");
if(sum < 0){
res.add(0, "-");
}
for (String e : res) {
System.out.print(e);
}
}
}
1002 A+B for Polynomials (25分)
import java.io.*;
import java.util.*;
class Main{
public static void main(String[] args) throws IOException {
List<Double> list = new LinkedList<>(); //链表中的多项式格式:coe1, exp1, coe2, exp2, coe3, exp3, ...
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
st.nextToken(); //丢弃项数K
while(st.hasMoreTokens()){
list.add(Double.valueOf(st.nextToken()));
}
st = new StringTokenizer(br.readLine());
st.nextToken(); //丢弃项数K
int i = 0;
while (st.hasMoreTokens()) {
double exp = Double.parseDouble(st.nexKtToken());
double coe = Double.parseDouble(st.nextToken());
while (i < list.size() && exp < list.get(i)) { //找到插入或者合并的位置
i += 2;
}
if (i >= list.size() || exp != list.get(i)) {
list.add(i, coe);
list.add(i, exp);
i += 2;
} else {
double newCoe = list.remove(i + 1) + coe;
if (newCoe == 0) {
list.remove(i); //两项相加系数为零,直接删掉
} else {
list.add(i + 1, newCoe); //将求和后的系数插入
}
}
}
if(list.size() == 0){
System.out.println("0");
return;
}
System.out.print(list.size() / 2 + " ");
for (int j = 0; j < list.size(); j++) {
double temp = list.get(j);
if (j % 2 == 0) {
System.out.print((int) temp + " ");
} else {
System.out.print(Math.ceil(temp * 10) / 10);
if(j != list.size() - 1)
System.out.print(" ");
}
}
}
}
1003 Emergency (25分)
dfs
题目给出各城市救援队数,相当于图的点权;给出城市之间的路径长,即边权。选择用邻接矩阵记录图中各顶点的联系。
可以利用深度优先搜索找目的地,如果遇到更短的路径,则更新:
- 最短路径长
- 到达路径数更新为1
- 最大可以搜集的救援队数
如果遇到和当前最短路径一样短的路径,则更新:
- 可以到达的路径数+1
- 判断是否需要更新最大可以搜集的救援队数
其它:
- 为了避免递归时在环路上绕圈,设置一个数组标志哪些顶点已经走过,避免dfs无限递归下去。
- 为了省去冗余计算,如果当前的路径长已经大于最短路径长了,直接让方法返回,即对递归进行剪枝。
import java.util.Scanner;
public class Main {
private static boolean[] visited;
private static int[] weight;
private static int[][] map;
private static int shortestPathCount;
private static int shortestDist;
private static int maxTeamCount;
public static void main(String[] args) {
//接收输入
Scanner sc = new Scanner(System.in);
int cityNum = sc.nextInt();
int roadNum = sc.nextInt();
int start = sc.nextInt();
int destination = sc.nextInt();
weight = new int[cityNum];
int count = 0;
while (count < cityNum) {
weight[count] = sc.nextInt();
count++;
}
map = new int[cityNum][cityNum];
//初始化
for (int i = 0; i < cityNum; i++) {
for (int j = 0; j < cityNum; j++) {
map[i][j] = -1;
}
}
visited = new boolean[cityNum];
count = 0;
while (count < roadNum) {
int c1 = sc.nextInt(), c2 = sc.nextInt();
int dis = sc.nextInt();
map[c1][c2] = dis;
map[c2][c1] = dis;
count++;
}
//初始化
shortestPathCount = 0;
shortestDist = Integer.MAX_VALUE;
maxTeamCount = 0;
findShortestPath(start, destination, 0, weight[start]);
System.out.println(shortestPathCount + " " + maxTeamCount);
}
private static void findShortestPath(int start, int dest, int dist, int currentWeight) {
if(dist > shortestDist) //剪枝
return;
if (start == dest) {
if (dist < shortestDist) {
maxTeamCount = currentWeight;
shortestDist = dist;
shortestPathCount = 1;
} else if(dist == shortestDist) {
shortestPathCount++;
maxTeamCount = maxTeamCount > currentWeight? maxTeamCount: currentWeight;
}
return;
}
for (int i = 0; i < map[start].length; i++) {
int nextDist = map[start][i];
if (nextDist == -1 || visited[i])
continue;
visited[i] = true;
findShortestPath(i, dest, dist + nextDist, currentWeight + weight[i]);
visited[i] = false;
}
}
}
Dijkstra
遇到同样长度的最短路径时更新策略跟dfs方法类似,但Dijkstra最短路径的查找原理是贪心算法。
import java.util.*;
import java.io.*;
class Main {
public static void main(String[] args) {
//接收输入
Scanner sc = new Scanner(System.in);
int cityNum = sc.nextInt();
int[][] map = new int[cityNum][cityNum];
int[] distance = new int[cityNum];
boolean[] visited = new boolean[cityNum];
int roadNum = sc.nextInt();
int initialCity = sc.nextInt();
int destination = sc.nextInt();
int[] weight = new int[cityNum];
int index = 0;
while(index < cityNum){
weight[index] = sc.nextInt();
index++;
}
for (int i = 0; i < cityNum; i++) {
for (int j = 0; j < cityNum; j++) {
map[i][j] = Integer.MAX_VALUE;
}
}
index = 0;
while(index < roadNum){
int c1 = sc.nextInt(), c2 = sc.nextInt(), dis = sc.nextInt();
map[c1][c2] = dis;
map[c2][c1] = dis;
index++;
}
//初始化
for (int i = 0; i < cityNum; i++) {
distance[i] = Integer.MAX_VALUE;
}
distance[initialCity] = 0;
int[] roadCount = new int[cityNum];
roadCount[initialCity] = 1;
int[] maxWeight = new int[cityNum];
maxWeight[initialCity] = weight[initialCity];
//Dijkstra
for (int i = 0; i < cityNum; i++) {
int minDis = Integer.MAX_VALUE, u = -1;
for (int j = 0; j < cityNum; j++) {
if(!visited[j] && distance[j] < minDis){
minDis = distance[j];
u = j;
}
}
if(u == -1)
break;
visited[u] = true;
for (int v = 0; v < cityNum; v++) {
int nextDis = map[u][v];
if(nextDis == Integer.MAX_VALUE || visited[v])
continue;
if(distance[u] + nextDis < distance[v]){
distance[v] = nextDis + distance[u];
roadCount[v] = roadCount[u];
maxWeight[v] = maxWeight[u] + weight[v];
} else if(distance[u] + nextDis == distance[v]){
roadCount[v] += roadCount[u];
maxWeight[v] = Math.max(maxWeight[v], maxWeight[u] + weight[v]);
}
}
}
System.out.println(roadCount[destination] + " " + maxWeight[destination]);
}
}