球队“食物链”
某国的足球联赛中有N支参赛球队,编号从1至N。联赛采用主客场双循环赛制,参赛球队两两之间在双方主场各赛一场。
联赛战罢,结果已经尘埃落定。此时,联赛主席突发奇想,希望从中找出一条包含所有球队的“食物链”,来说明联赛的精彩程度。“食物链”为一个1至N的排列{ T1,T2, …,TN },满足:球队T1战胜过球队T2,球队T2战胜过球队T3,……,球队T(N-1)战胜过球队TN,球队TN战胜过球队T1。
现在主席请你从联赛结果中找出“食物链”。若存在多条“食物链”,请找出字典序最小的。
注:排列{ a1,a2,…,aN }在字典序上小于排列{ b1,b2, … ,bN },当且仅当存在整数K(1 <= K <= N),满足:aK < bK且对于任意小于K的正整数i,ai=bi。
输入格式:
输入第一行给出一个整数N(2 <= N <= 20),为参赛球队数。随后N行,每行N个字符,给出了NxN的联赛结果表,其中第i行第j列的字符为球队i在主场对阵球队j的比赛结果:“W”表示球队i战胜球队j,“L”表示球队i负于球队j,“D”表示两队打平,“-”表示无效(当i=j时)。输入中无多余空格。
输出格式:
按题目要求找到“食物链”T1,T2 ,…,TN,将这N个数依次输出在一行上,数字间以1个空格分隔,行的首尾不得有多余空格。若不存在“食物链”,输出“No Solution”。
输入样例1:
5
-LWDW
W-LDW
WW-LW
DWW-W
DDLW-
输出样例1:
1 3 5 4 2
输入样例2:
5
-WDDW
D-DWL
DD-DW
DDW-D
DDDD-
输出样例2:
No Solution
学校去年举办的程序设计大赛,当时大一只做出来几个水题,后面的大题根本看不懂,时隔将近一年想回去试试能不能AC了那些题。。。。。。事实证明,还有些差距。下面将给出我的思路。
无题解纯自己思考,看完题目想到了TSP问题,算法还算是给了我一定的思绪,我记得好像可与用dfs()解决。
但是做的过程中发现,输入的数据会发生一些问题,仔细排查后原来是由于nexLine()会读取上一个回车导致的,之前也遇到过,只是当时搞明白之后就没有再碰。
接下来就是自己手写dfs(),第一次尝试自己写,而看着模板,但是发现好几个点过不去,比如如何确定跳出时机,如何实现字典序输出,我在主函数写f(1)这不是只能是1开头了。很迷。下面的代码运行不出结果。
import java.util.Scanner;
public class Main {
static String[][] str;
static int n;
static int cnt = 0;
static boolean[][] vis;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
n = in.nextInt();
str = new String[n + 1][n + 1];
vis = new boolean[n + 1][n + 1];
/**
* 注意nextLine()会读取上一个回车
* */
for (int i = 0; i < n+1; i++) {
String s = in.nextLine();
str[i] = s.split("");
}
f(1);
// for (int i = 1; i < n+1; i++) {
// for (int j = 1; j < n+1; j++) {
// System.out.print(str[i][j] + " ");
// }
// System.out.println();
// }
}
private static void f(int m) {
// TODO Auto-generated method stub
if (cnt > m) {
}
for (int i = 1; i < n+1; i++) {
for (int j = 1; j < n+1; j++) {
if (str[i][j].equals("W")) {
vis[i][j] = true;
f(j);
}
}
}
}
}
接下来看题解,一开始就发现自己做了一个非常繁琐的操作进行存储数据,而题解的做法是直接用boolean数组存,‘W’是true,‘L’是false,巧妙不少。结尾输出的方式也是巧妙,第一个不打印空格,之后都在打印之前加一个空格,可以巧妙的避免结尾的空格影响AC。
这道题跟单纯的TSP问题区别就在于TSP是对于无向赋权图来说找出最短的哈密顿回路,而这道题是对于有向无权图来说的(为什么是有向的,这是因为主客场制出现A在主场赢了B,A在客场也赢了B的情况)。当然剪枝之后效率会更好,但是蒟蒻的我还是不要把自己越搞越迷糊的好。
import java.util.Scanner;
public class Main {
static boolean[][] a;
static int n;
static int cnt = 0;
static int flag = 0;
static int[] res;
static boolean[] vis;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
n = in.nextInt();
a = new boolean[n + 1][n + 1];
vis = new boolean[n + 1];
res = new int[n + 1];
/**
* 注意nextLine()会读取上一个回车
* */
for (int i = 0; i <= n; i++) {
String s = in.nextLine();
for (int j = 0; j < s.length(); j++) {
if (s.charAt(j) == 'W') {
a[i][j+1] = true;
}
if (s.charAt(j) == 'L'){
a[j+1][i] = true;
}
}
}
f(1, 1);
if (flag == 1) {
for (int i = 1; i <= n; i++) {
System.out.print(i == 1 ? "" : " ");
System.out.print(res[i]);
}
} else {
System.out.println("No Solution");
}
}
private static void f(int cur, int num) {
if (flag == 1) {
return;
}
res[cur] = num;
if (cur == n && a[num][1] == true) {
flag = 1;
return;
}
if (cur == n) {
return;
}
vis[num] = true;
for (int i = 1; i <= n; i++) {
if (vis[i] == false && a[num][i] == true) {
f(cur + 1, i);
}
}
vis[num] = false;
}
}