sgu 138解题记录

来源:互联网 发布:oracle云计算产品 编辑:程序博客网 时间:2024/05/20 19:47

138. Games of Chess

time limit per test: 0.25 sec. 
memory limit per test: 4096 KB

N friends gathered in order to play chess, according to the following rules. In the first game, two of the N friends will play. In the second game, the winner of the first game will play against another friend (maybe even the same friend who lost the first game). In the third game, the winner of the second game will play against someone else and so on.. No game will end as a draw (tie). Given the number of games each of the N friends played, find a schedule for the games, so that the above rules are obeyed.

Input

The first line contains the number of friends N (2<=N<=100). The second line contains N integers, separated by blanks, representing the number of games each friend played. The first number represents the number of games played by the first friend, the second number represents the number of games played by the second friend and so on..

Output

The first line should contain the number of games played by all the friends (it will be an integer between 1 and 10 000, for every test case). Let's suppose this number is G. Then, G lines follow, each of them containing two integers, describing the games. The first line contains the numbers of the two friends who played the first game. The friend printed first is considered to be the winner. Each of the next G-1 lines contain the integers a and b, where a<>b and a or b is the winner of the previous game. The friend printed first on the line is considered to be the winner of the game. 
It is guaranteed that for every test case there will be at least one possible scheduling of the games.

Sample Input

42 4 1 5

Sample Output

64 34 12 42 14 22 4

解题记录:

        第一想法:把每个参赛人员想象成一个颜色各不相同的板子,宽度都一样是1,长度则为参与次数,同时分出:胜者组和败者组。由于要求不能自己和自己对战,也就是说横向相邻的木块颜色不能相同。那就根据参赛次数从大到小排序,先在胜者组填充,然后再填充到败者组。此时准备写的时候,猛然发现忽略了一个细节,就是胜利者必须在下一场出现,那么就得考虑把胜者组的那些次数分最后一个到败者组,这样才可以完成完美过度。

解题报告:

        由于保证了每个数据都一定有解,那么就按照参加次数从大到小排序,先从胜者组开始安排,在胜者组中,当参赛次数只剩最后一个的时候,分入败者组,保证胜者组的完美过渡。败者组就把剩下的都往里面填充就够了。

PS:为啥按照从大到小就不会相遇呢 = =,我连严谨的所以然也说不出来,更别说证不出来,只是一直以来的感觉。标记以后再证。

代码:

#include <cstdio>#include <algorithm>using namespace std;int n, cnt;int a[110], win[10010], lose[10010];void init() {scanf("%d", &n);for (int i = 1; i <= n; i++) {scanf("%d",&a[i]);cnt += a[i];a[i] = (a[i]<<16)+i;}sort(a+1, a+n+1);}void solve() {int x=n;cnt /= 2;printf("%d\n", cnt);for (int i = 1; i <= cnt; i++) {if ((a[x]>>16) == 1) {lose[i]=a[x]&0xffff;x--;}win[i]=a[x]&0xffff;a[x] -= 1<<16;}for (int i = 1; i <= cnt; i++) {if (lose[i] != 0)  continue;if ((a[x]>>16) == 0)  x--;lose[i]=a[x]&0xffff;a[x] -= 1<<16;}for (int i = 1; i <= cnt; i++)printf("%d %d\n", win[i], lose[i]);}int main() {init();solve();}

0 0
原创粉丝点击