题目
思路
代码
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;
const int maxn = 1024 + 10;
char table[maxn][maxn];
int main(){
int n;
while (scanf("%d", &n) == 1 && n) {
for (int i = 1; i <= n; i++) scanf("%s", table[i] + 1); //目的:横纵都为非0开头的计数
vector<int> win, lose; //队1可以赢和可以输的队伍
for (int i = 2; i <= n; i++)
if (table[1][i] == '1') win.push_back(i);
else lose.push_back(i);
int nt = n; // nt为当前一局,还剩多少队伍
while (nt > 1) {
vector<int> win2, lose2, final; // win2,lose2为下一局,final为3/4阶段
// 阶段1
for (int i = 0; i < lose.size(); i++) {
int tlose = lose[i];
bool matched = false;
for (int j = 0; j < win.size(); j++) {
int &twin = win[j]; // c++引用的应用
if (twin > 0 && table[twin][tlose] == '1') {
printf("%d %d\n", twin, tlose); // 边solve边输出.jpg
win2.push_back(twin); // 将其进阶到下一轮
twin = 0; // 此局中twin不可用了
matched = true;
break;
}
}
if (!matched) final.push_back(tlose); // 将其放入3/4阶段
}
// 阶段2
bool first = true;
for (int i = 0; i < win.size(); i++) {
int twin = win[i];
if (twin > 0) // twin在此局中没用到
if (first) { printf("1 %d\n", twin); first = false; } // 给队伍1任意配对
else final.push_back(twin); // 将剩余的灰色队推给3/4阶段
}
// 阶段3/4
// 此处应该注意final中的队伍顺序,是黑色全都在前面,灰色全都在后面,因此相邻打一场可行
// 此处正体现了此代码的精妙之处
for (int i = 0; i < final.size(); i += 2) {
printf("%d %d\n", final[i], final[i + 1]);
int keep = final[i];
if (table[final[i + 1]][final[i]] == '1') keep = final[i + 1];
if (table[1][keep] == '1') win2.push_back(keep);
else lose2.push_back(keep);
}
win = win2;
lose = lose2;
nt >>= 1;
}
}
return 0;
}
感受
1.整道题的思路比较玄幻。。。LRJ的代码也给人一种一气呵成之感。。。
学不来。。学不来。。。
2.属于有空没空多看看的难题系列