救濟金髮放(uva-133)
阿新 • • 發佈:2018-12-26
N個人占城一圈,逆時針編號為1~n.有兩個官員,A從1開始逆時針數,B從n順時針開始。在每一輪中,官員A數k個數就停下來,官員B數m個就停下來(注意有可能連個官員停在同一個人上)。接下來被官員選中的人離開隊伍。
輸入n,k,m輸出每輪裡被選中的人的編號(如果有兩個人)先輸出被A選中的)。注意:輸出的每個數應當恰好佔3列。
【分析】
仍然採用自頂向下的方法編寫程式,用一個大小為0的陣列表示人站成的圈。為了避免人走之後移動陣列元素,用0表示離開隊伍的人,數數時跳過即可。主程式如下:
還有一種方法,不過顯得有點繁瑣:#include const int MAXN = 25; int n,k,m; int a[MAXN]; int go(int p, int d, int k);//數過k個人,開始位置p必須是數1時候的前一個位置。 int main() { while (scanf("%d%d%d", &n, &k, &m) == 3 && n) { for (int i = 0; i < n; i++) {//逆時針編號 a[i] = i + 1; } int left = n; int pA = n-1, pB = 0; int pANext,pBNext; while (left) { pA = go(pA, 1, k);//1表示逆時針,因為它是逆時針標號,從n的前一位開始 pB = go(pB, -1, m);//-1表示順時針。從1的下一位開始 printf("%3d", pA + 1); left--; if (pA != pB) { printf("%3d", pB + 1); left--;} a[pA] = a[pB] = 0;//選到的人標記為0,下次遇到後跳過 if (left) printf(","); } printf("\n"); } return 0; } int go(int p, int d, int L) { while (L--) { do { p = (p+n+d)%n;} while(a[p] == 0); } return p; }
ps:主要步驟我在後面都寫了註釋#include using namespace std ; const int maxn = 10000 ; int queue1[maxn] , queue2[maxn] ; void init( int n ) { memset( queue1 , 0 , sizeof( queue1 ) ) ; memset( queue2 , 0 , sizeof( queue2 ) ) ; //正逆兩個方向分別用兩個陣列記錄編號 for( int i = 0 ; i < n ; i++ ) queue1[i] = i + 1 ; int count = 0 ; for( int i = n - 1 ; i >= 0 ; i-- ) queue2[count++] = queue1[i] ; return ; } int find( int a , int arr[] , int begin , int end ) { int pos = -1 ; for( int i = begin ; i < end ; i++ ) if( arr[i] == a ) { pos = i ; break ; } return pos ; } void change( int a[] , int pos , int end ) { for( int i = pos ; i < end -1 ; i++ ) a[i] = a[i+1] ; return ; } int main() { int n = 0 , m = 0 , k = 0 ; while( cin >> n >> m >> k ) { if( ! n && ! m && ! k ) break ; init( n ) ; int front1 = 0 , front2 = 0 ; int rear1 = n , rear2 = n ; int count = 0 ; int flag = 0 ; while( rear1 > front1 ) //當佇列不為空 { if( flag ) cout << "," ; flag = 1 ; //順時針找下一個人,並讓不是下一個人的人重新入隊 for( int i = 0 ; i < m - 1 ; i++ ) queue1[rear1++] = queue1[front1++] ; int first = queue1[front1] ; //逆時針找下一個人,並讓不是下一個人的人重新入隊 for( int i = 0 ; i < k - 1 ; i++ ) queue2[rear2++] = queue2[front2++] ; int second = queue2[front2] ; //輸出找到的人 if( first == second ){ printf( "%3d" , first ) ; count++ ;} else { printf( "%3d%3d" , first , second ) ; count += 2 ; } //找應該刪除的人,並且刪除 int pos = find( first , queue1 , front1 , rear1 ) ; if( pos != -1 && pos > front1 )//pos < front1說明這個位置不在佇列裡 { change( queue1 , pos , rear1 ) ;rear1-- ; }//每刪除一個就要把隊尾指標給往回倒一 pos = find( second , queue1 , front1 , rear1 ) ; if( pos != -1 && pos > front1 ) { change( queue1 , pos , rear1 ) ;rear1-- ; } pos = find( first , queue2 , front2 , rear2 ) ; if( pos != -1 && pos > front2 ) { change( queue2 , pos , rear2 ) ; rear2-- ; } pos = find( second , queue2 , front2 , rear2 ) ; if( pos != -1 && pos > front2 ) { change( queue2 , pos , rear2 ) ; rear2-- ; } front1++ ; front2++ ;//隊首元素出隊 } if( count < n ) printf( ",%3d" , queue1[rear1] ) ; cout << endl ; } return 0 ; }