天梯賽每年有大量參賽隊員,要保證同一所學校的所有隊員都不能相鄰,分配座位就成為一件比較麻煩的事情。為此我們制定如下策略:假設某賽場有 N 所學校參賽,第 i 所學校有 M[i] 支隊伍,每隊 10 位參賽選手。令每校選手排成一列縱隊,第 i+1 隊的選手排在第 i 隊選手之后。從第 1 所學校開始,各校的第 1 位隊員順次入座,然后是各校的第 2 位隊員…… 以此類推。如果最后只剩下 1 所學校的隊伍還沒有分配座位,則需要安排他們的隊員隔位就坐。本題就要求你編寫程序,自動為各校生成隊員的座位號,從 1 開始編號。
輸入格式:
輸入在一行中給出參賽的高校數 N (不超過100的正整數);第二行給出 N 個不超過10的正整數,其中第 i 個數對應第 i 所高校的參賽隊伍數,數字間以空格分隔。
輸出格式:
從第 1 所高校的第 1 支隊伍開始,順次輸出隊員的座位號。每隊占一行,座位號間以 1 個空格分隔,行首尾不得有多余空格。另外,每所高校的第一行按“#X”輸出該校的編號X,從 1 開始。
輸入樣例:3 3 4 2輸出樣例:
#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
被這道題坑的很慘,可能是有些輕視這道題的分量了,以至於不嚴謹,最后補題還是想了很多思路,終於做對了 好好記錄一下。
代碼:
#include <iostream>///好坑的題目比賽的時候沒做出來,自以為寫的很對,結果只得了三分,自己真菜。 #include <cstdio>///題目要求說的很清楚,每個學校的人先排成一縱隊,由低到高,然后就是排着插入座位,每個學校一個人,如果最后只剩下一個學校的人沒安排完就要間隔入座 #include <cstring>///總不能排着每個座位去找該入座的人吧,看一下最多有多少隊,然后從第一隊開始,看看有s[0]個學校有第一隊,那么第一隊排座位,同一個學校相鄰座位差就是是s[0],由於是按每個學校輸 #include <cstdlib>///還需要確定每一隊的第一個人的位置。 #include <algorithm> #include <map> using namespace std; int n,m[101],t[101][10],s[101],c,d,e;///n 個學校 每個學校的隊伍數m[] 對應於每一隊伍首個人的位置t[][] s[j]代表有幾個學校含有第j + 1隊 c,d,d做循環記錄用 int main() { ///以測試樣例為例 ///3 ///3 4 2 cin>>n;///n = 3 for(int i = 0;i < n;i ++) { cin>>m[i]; if(m[i] > d)d = m[i];///d記錄單個學校最多有多少隊 } ///m[0] = 3 m[1] = 4 m[2] = 2 d = 4 e = d;///e = 4 while(d --)///對於每一隊 { int p = 1,q = c;///c記錄前面已經安排了多少個隊入座 for(int i = 0;i < n;i ++) { if(m[i] >= e - d)///第i + 1個學校是否有第e - d隊 有 則執行 { t[i][e - d - 1] = q * 10 + p; c ++;///安排完一隊 c就加1 p ++;///對於第e - d隊,下一個學校如果含有這一隊 那么首個人編號應該 是當前 t[i][e - d - 1] + 1,方便起見用p記錄,每次加1當到下一隊p又重新計算 } } s[e - d - 1] = p - 1;///p初始就是1 所以有 p - 1個學校有>= e - d個隊 if(p - 1 == 1)break;///只剩下一個學校了 不用繼續記錄了后面直接全部輸出 } /* 第一遍循環 d --值為4 循環執行 d = 3 當前是第1隊(e - d = 1) p = 1 q = 0(c = 0 前面有0個隊) 開始for循環 t[0][0] = 1 c = 1 p = 2 然后t[1][0] = 2 c = 2 p = 3 然后t[2][0] = 3 c = 3 p = 4 for循環結束 s[0] = 3,表示有三個學校含有第一隊 寫成這樣估計有復習的時候肯定能看懂~ */ for(int i = 0;i < n;i ++)///開始輸出 { printf("#%d\n",i + 1); for(int j = 0;j < m[i];j ++) { if(s[j] == 1)///如果只剩下這一個學校有這一隊,那么如果有更多隊也一定只有這個學校才有 所以直接全部輸出 { if(j && s[j - 1] * 9 + 1 + t[i][j - 1] == t[i][j])t[i][j] ++;///如果到這里最后一個座位的人是這個學校的 那么 需要隔一個位置比如樣例中 是82 而根據前面的推算每一隊第一位位置會是81 而 2 * 9 + 1 + 62 = 81 滿足if語句 加一變成82 for(int k = 0;k < (m[i] - j) * 10;k ++) { printf("%d",t[i][j] + k * 2); if(k % 10 == 9)putchar('\n'); else putchar(' '); } j = m[i] - 1;///可以讓循環停止 } else { for(int k = 0;k < 10;k ++) { if(!k)printf("%d",t[i][j] + s[j] * k); else printf(" %d",t[i][j] + s[j] * k); } putchar('\n'); } } } }
備賽重溫:
代碼:
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int n; int s[101]; int num[11]; int dif[11]; int main() { scanf("%d",&n); for(int i = 1;i <= n;i ++) { scanf("%d",&s[i]); for(int j = 1;j <= s[i];j ++) { num[j] ++; } } for(int i = 1;i <= n;i ++) { printf("#%d\n",i); int d = i; for(int j = 1;j <= s[i];j ++) { d += num[j - 1] * 10 + dif[j - 1]; if(num[j] == 1) num[j] ++; for(int k = 0;k < 10;k ++) { if(k) putchar(' '); printf("%d",d + k * num[j]); } putchar('\n'); } if(num[s[i] + 1] != 1) dif[s[i]] --; } }