题目大意:
有n个人在下象棋,每次赢了的人接着下,输的人可以继续,也可以换个人下。现在告诉你每个人下的盘数,让你构造一组对弈方案。
Sample Input
4
2 4 1 5
Sample Output
6
4 3
4 1
2 4
2 1
4 2
2 4
分析:
构造题。
首先把玩的局数和人的编号一起从大到小排序,以局数为关键字。
以样例来说:
局数:5 4 2 1
编号:4 2 1 3
我们用两个数组win和lose记录每一局的输赢,从大到小依次考虑每个人,若当前人的剩余局数等于一,则把他填进lose里;否则填进win里
以样例来说:
win: 4 4 4 4 2 2
lose: 2 2 1 1 4 3
代码如下:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mp make_pair
#define pb push_back
#define x first
#define y second
using namespace std;
typedef pair<int, int> pii;
inline int read()
{
int x = 0, f = 1, t = getchar();
while(t < '0' || t > '9') {
if(t == '-') f = -1;
t = getchar();
}
while(t >= '0' && t <= '9') {
x = (x<<1) + (x<<3) + t - '0';
t = getchar();
}
return x * f;
}
const int maxn = 105;
const int maxa = 10005;
int n, sum;
pii data[maxn], ans[maxa];
void init()
{
register int i;
for(n = read(), i = 1; i <= n; ++i)
data[i] = make_pair(read(), i), sum += data[i].x;
sum >>= 1;
sort(data + 1, data + n + 1, greater<pii>());
}
void work()
{
register int i, j;
for(i = 1, j = 1; i <= sum; ++i) {
if(data[j].x == 1) data[j].x = 0, ans[i--].y = data[j++].y;
else --data[j].x, ans[i].x = data[j].y;
}
for(i = 1, j = 1; i <= n && j <= sum; ++j) {
while(!data[i].x) ++i;
if(!ans[j].y) ans[j].y = data[i].y, --data[i].x;
}
printf("%d\n", sum);
for(i = 1; i <= sum; ++i)
printf("%d %d\n", ans[i].x, ans[i].y);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
init();
work();
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}