UVa-133 The Dole Queue(约瑟夫环)

题意:為了縮短領救濟品的隊伍,NNGLRP決定了以下策略:每天所有來申請救濟品的人會被放在一個大圓圈,面朝裡面。選定一個人為編號 1 號,其他的就從那個人開始逆時針開始編號直到 N。一個官員一開始逆時針數,數 k 個申請者,然後另一個官員第 N 個始順時針方向數 m 個申請者,這兩個人就被送去再教育。如果兩個官員數的是同一個人,那個人則被送去從政,然後2個官員再在剩下的人裡面繼續選直到沒人剩下來,注意兩個被選中的人是同時走掉的,所以就有可能兩個官員選中一個人。

例子:sample input:10 4 3                             sample output:4  8,  9  5,  3  1,  2  6, 10,  7
                                   13 17 42                                                   4 11, 10  1,  8  6, 13  7,  3,  5 12,  9  2
                                   7 8 47                                                      1  3,  5  7,  2  4,  6
                                   0 0 0
    

分析:一道模拟题,用vis数组来标记该数有没有被选过,然后用两个循环,因为是同时发生,所以去掉以及输出的操作放在最后,要注意输出格式          


#include<iostream>
#include<cstring>
using namespace std;

int N, k, m;
int arr[25];
int vis[25];

int main(){
	
	while(cin>>N>>k>>m && N){
		int num = 0; //num来表示一共去掉了几个数
		for(int i = 1; i<=N; i++){
			arr[i] = i;
			vis[i] = 1;
		}
		int A = 0, B = N+1;
		int A_num = 0, B_num = 0; //用来记录数了多少个
		int flagA, flagB; //用来判断A和B是不是同一个数
		while(num<N){
			int temp = 0;
			flagA = 0; flagB = 0;
			for(;;){
				A++;
				if(A>N) A = 1;
				if(vis[A]){
					A_num++;
					if(A_num == k){
					    flagA = 1;
					    A_num = 0;
					    num++;
					    printf("%3d", A);
					    temp = A;
					    break;
					}
				}
		   }
			
			for(;;){
				B--;
				if(B<1) B = N;
				if(vis[B]){
					B_num++;
					if(B_num == m){
					    flagB = 1;
					    B_num = 0;
					    num++;
					    if(temp!=B) printf("%3d", B);
					    break;
					}
				}
			}
			if(flagA && flagB && A==B) num--;
			if(num<N) printf(",");
			if(flagA) vis[A] = 0;
			if(flagB) vis[B] = 0;
		}
		printf("\n");	
	}
	return 0;
}

                    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值