链接:http://acm.zzuli.edu.cn/problem.php?id=2494
时间限制: 1 Sec 内存限制: 128 MB
提交: 74 解决: 20
[提交] [状态] [讨论版] [命题人:admin]
题目描述
每到考试时,为了保证每位同学和其周围的同学都不认识,小明想出了如下策略:
假设某个考场有 N 个学校的考生,第 i 所学校有 t名考生参加考试。令每校考生排成一列纵队,第 i+1 队的考生排在第 i 队考生之后。
从第 1 所学校开始,各校的第 1 位考生顺次入座,然后是各校的第 2 位考生…… 以此类推。如果最后只剩下 1 所学校还没有分配座位,则需要安排他们的考生隔位就坐。
但是小明不会为各校的考生分配座位号,请你为各校考生自动生成座位号,从 1 开始编号。
输入
第一行输入参加考试的学校数 N (不超过100的正整数);第二行输入 N 个不超过100的正整数(确保给出的整数都是10的倍数),其中第 i 个数对应第 i 所学校的考生人数,数字间以空格分隔。
输出
从第 1 所学校的开始,顺次输出考生的座位号。每10名考生占一行,座位号间以 1 个空格分隔,行首尾不得有多余空格。另外,每所学校的第一行按“#X”输出该校的编号X,从 1 开始。
样例输入 Copy
3
30 40 20
样例输出 Copy
#1
1 4 7 10 13 16 19 22 25 28
31 34 37 40 43 46 49 52 55 58
61 63 65 67 69 71 73 75 77 79
#2
2 5 8 11 14 17 20 23 26 29
32 35 38 41 44 47 50 53 56 59
62 64 66 68 70 72 74 76 78 80
82 84 86 88 90 92 94 96 98 100
#3
3 6 9 12 15 18 21 24 27 30
33 36 39 42 45 48 51 54 57 60
题意开始有点没懂,看下样例,应该就能明白。例如样例:即1排到1,2排到2,3排到3,然后4再排到1
排到第30个时,第三组没位置了,所以再从第一组的第三排 从31开始,继续模拟上述操作。所以这题可以
枚举每一行的情况,进行排列,然后再输出。有一个特殊情况,就是行数最大的那行,要跟该组上一行的最后
一个数比较下,是否加1,例如样例中的第二组,排完前三列后,数目为80,这时不能加1,要+2.
#include<iostream>
#include<algorithm>
using namespace std;
#define N 110
int a[N][N][N];
int b[N];
int main(){
int n, cnt = 1;
cin >> n;
int MX = 0;
for(int i = 1; i <= n; i++)
{
cin >> b[i];
MX = max(MX, b[i]);
}
int M_ = 0; //用来特判单独一行
int now = 1;
for(int i = 1; i <= MX / 10; i++) //枚举行
{
int cnt = 0;
for(int u = 1; u <= n; u++) //统计有几组可以排这一行
if(b[u] >= i * 10)
cnt++;
if(cnt)
{
if(cnt < 2)
{
cnt = 2;
if(now == M_ + 1) //判断最后 单独排一行的情况
now++;
}
int x = 1;
int base = now, re = 0;
for(int j = 1; j <= n; j++)
{
if(b[j] >= i * 10)
{
for(int k = 1; k <= 10; k++)
{
a[j][i][k] = base;
base += k != 10 ? cnt : 0;
re = base; //用于更新下一次起始数字
M_ = max(M_, base);
}
base = now + x, x++; // 下一组的 该行开始数字
}
}
now = re + 1; //下一行从now这个数开始排
}
}
for(int i = 1; i <= n; i++)
{
printf("#%d\n", i);
for(int j = 1; j <= b[i] / 10; j++, cout << endl)
for(int k = 1; k <= 10; k++)
if(k != 10)
cout << a[i][j][k] << " ";
else
cout << a[i][j][k];
}
return 0;
}