UVa 133 The Dole Queue(圈的下標處理)
阿新 • • 發佈:2018-12-26
本題難點在於用陣列處理圈狀物時下標的計算。
#include <cstdio>
#include <string.h>
using namespace std;
const int maxn=25;
int main(){
int n,k,m;
while(scanf("%d%d%d",&n,&k,&m)==3&&n){
int people[maxn];
memset(people,0,sizeof(people));
int currA=0,currB=n+1,left=n; //用left記錄剩下的人,作為迴圈終止的條件
while(left){
//利用下標模擬官員AB的運動
int i=k,j=m;
while(i) {currA=(currA+1+n-1)%n+1;if(!people[currA])i--;}
while(j){currB=(currB-1+n-1)%n+1;if(!people[currB])j--;}
if(currA==currB){
people[currA]=1;
left--;
printf("%3d",currA);
}
else{
people[currA]=people[currB]=1 ;
left-=2;
printf("%3d%3d",currA,currB);
}
if(left) printf(","); //輸出的處理,別怕“,”
}
printf("\n");
}
return 0;
}
注意點:
- 變數left的應用
相較於用left簡潔明瞭,自己通過遍歷整個陣列來判斷迴圈是否應該結束的方法麻煩冗長而且使“,”的列印不便。
bool End=false;
……
for(int a=1;a<=n;a++){
if(!people[a]) break ;
if(a==n) End=true;
}
啟示:當迴圈與當且有效的元素個數(本題是還沒有出隊的人)有關時,可以設定一個計數變數。
2.“,”的列印
首先克服自己看到這樣的輸出:完整的一個輸出需要分段輸出,且中間不是換行而是空格、逗號等而且還要求不能多輸出空格、逗號(如本題一次輸出的最後不在需要逗號)時的恐懼感。
接下來是解決方案:
仔細分析“,”或者空格出現的條件,或者說是與輸出正文的關係; 直接用語句printf(“,”);(怕啥,不就是一句話的事嗎= =)
3.圈狀迴圈陣列的下標處理:
利用取餘運算,關注頭尾的處理。
然後本題中,對於currA、currB的處理,之前是這麼寫的:
while(i) {currA++; if(!people[(currA+1+n-1)%n+1])i--;}
currA++ 會使currA一直增加而不是迴圈。