L1-049 天梯赛座位分配(新解法,详细注释)
一、题目分析
首先,题目意思还是比较好理解的,就是依次排位置,前面的高校先排,例如,我们有A、B、C三所高校,分别有若干支队伍,A1表示高校A的第一支队伍,A11表示高校A的第一支队伍的第一名队员的位置。
那么,座位安排如下:A11,B11,C11,A12…A21,B21,C21…
后面就是依次往后排了。
二、解题思路
我发现很多题解都是依次遍历,当然,我自己也尝试过,确实是可以做出来的。但我发现这道题是有一定规律的,类似于等差数列,把每支队伍看成一个等差数列,那么我们只需要知道每个数列的首项和公差即可。
三、代码实现
#include<bits/stdc++.h>
using namespace std;
#define pai pair<int,int>
const int N=110;
//m[i]表示第i所高校的队伍数
int m[N];
//用于存储每所高校的次序和队伍数:<次序,队伍数>
vector<pai> st;
int main(){
int n;
cin>>n;
//初始化
for(int i = 1;i <= n;i++){
cin>>m[i];
pai p(i,m[i]);
st.push_back(p);
}
//根据队伍数,将st升序排序(采用拉姆达表达式书写自定义排序函数)
sort(st.begin(),st.end(),[](pai a,pai b){ return a.second<b.second; });
//依次输出每所高校队伍座位情况
for(int i = 1;i <= n;i++){
cout<<"#"<<i<<endl;
//id表示当前座位,每所高校初始座位为i
//k表示还未完全排完的高校数,初始化为n
//v表示st的下标,指向还未排完的高校中队伍数最少的,初始化为0
//dt表示第i所高校相邻队员所隔开的位置数,如果只有一所高校,则初始化为1,否则初始化为n
int id = i,k = n,v = 0,dt = n==1? 2: n;
//依次输出第i所高校的队伍座位表,x表示高校的第x支队伍
for(int x = 1;x <= m[i];x++){
for(int j = 1;j <= 10;j++){
cout<<id;
if(j != 10)cout<<' ';
else puts("");
id+=dt;
}
//当有高校所有队伍已经安排完了,dt需要更新(注意排位置是每所高校同步的)
while(v < st.size()&&x == st[v].second){
//队伍数-1
k--;
//如果不是只剩下当前一所高校,并且次序在前的高校所有队伍排完了,则当前高校的下一支队伍的第一个位置号要-1
if(k != 1&&st[v].first < i)
id--;
v++;
}
//更新dt,如果只有一所高校,dt=2,否则dt=k;
dt = k==1? 2:k;
}
}
return 0;
}