DHU OJ | 進階練習19-約瑟夫環2 | 模擬+特判

19 約瑟夫環2

作者: SunCiHai時間限制: 10S章節: 循環

問題描述 :

明明是一名公安局的談判專家,專門負責和綁匪談判。有一次,明明接到一個特殊的任務,他趕到了案發現場,發現有k個綁匪綁架了k個人質,於是明明就開始和綁匪進行談判。綁匪提出了一個非常特殊的要求,如果明明能夠回答出這個問題,那綁匪將釋放所有的人質;否則,綁匪就要撕票。 綁匪的問題是這樣:綁匪把人質和自己圍成一個圈,把人質從1開始編號,一直編到k,然後綁匪自己從k+1開始編號,一直編到2k。現在從編號1開始,每次從其中選出第m個人(隔m-1選出一個人)出列,然後綁匪要求明明選定這個m值,且m值要儘量的小,使得最先出列的k個人都是綁匪。 例如:有3個壞人和3個人質,他們排成一圈,其中編號1到3的爲人質,編號4到6的爲壞人,如下: 1、2、3、4、5、6; 明明要選定m=5時,能夠滿足綁匪的要求。因爲: 第一輪,從1開始數,編號5出列,剩下的人爲: 1、2、3、4、6; 第二輪,從6開始數,編號4出列,剩下的人爲: 1、2、3、6; 第三輪,從6開始數,編號6出列,剩下的人爲: 1、2、3; 這樣所有的綁匪都先出列,明明可以成功地救出所有的人質。 如果明明能夠找到這個m值,那麼所有的人質都想獲救,否則的話,後果不堪設想。明明意識到了問題的嚴重,這個問題對他來說十分地棘手。於是明明想到了你,你是一名程序設計專家,明明想讓你用程序來解這個問題,救出所有的人質。 明明的問題可以歸結爲:假設有k個人質和k個綁匪圍成一圈。人質的編號從1到k,綁匪的編號從k+1到2k。從編號1開始,每次從其中選出第m個人(隔m-1選出一人)出列。希望求出m的最小值,使得最先出列的k個人都是綁匪,即都是編號從k+1到2k的人。

輸入說明 :

你寫的程序要求從標準輸入設備中讀入測試數據作爲你所寫程序的輸入數據。標準輸入設備中有多組測試數據,每組測試數據僅一行,每組測試數據有一個整數k(1≤k≤10),表示人質的人數和綁匪的人數。每組測試數據與其後一組測試數據之間沒有任何空行,第一組測試數據前面以及最後一組測試數據後面也都沒有任何空行。

輸出說明 :

對於每一組測試數據,你寫的程序要求計算出一組相應的運算結果,並將這一組運算結果作爲你所寫程序的輸出數據依次寫入到標準輸出設備中。每組運算結果爲一個整數m,即明明要選定的那個數。每組運算結果單獨形成一行數據,其行首和行尾都沒有任何空格,每組運算結果與其後一組運算結果之間沒有任何空行,第一組運算結果前面以及最後一組運算結果後面也都沒有任何空行。 注:通常,顯示屏爲標準輸出設備。

輸入範例 :

1
2
3
5

輸出範例:

2
7
5
169

筆記

這道題我用了循環鏈表模擬,寫的時候把判空條件搞錯了,坑了自己好久。

//循環鏈表判空條件
head->next==head

//我順手寫成了這個。。
head->next==NULL

另外,這道題k的數據範圍是[1,10],我尋思也不大啊,就暴力唄,誰知道當k=10的時候耗時大大增加,就超時了。

對,當且僅當k=10的時候會超時,因此我對這種情況做了特判。

……暫時還沒想其它好辦法。

代碼

#include<stdio.h>
#include<stdlib.h>

struct linkList{
	int num;
	struct linkList *next;
};

struct linkList *head = NULL;

void init(){
	if(head!=NULL){
		while(head->next!=head){
			struct linkList *p = NULL;
			p = head->next;
			head->next = p->next;
			free(p);
		}
		free(head);
	}
	
}

void createLinkList(int k){
	init();
	head = (struct linkList*)malloc(sizeof(struct linkList));
	head->num = 1;
	head->next = NULL;
	
	int i;
	struct linkList *p = NULL;
	p = head;
	for(i=2;i<=2*k;i++){
		struct linkList *q = NULL;
		q = (struct linkList*)malloc(sizeof(struct linkList));
		q->num = i;
		q->next = NULL;
		p->next = q;
		p = p->next;
	}
	p->next = head;
}
int main(){
	int k;
	int flag = 1;
	while(scanf("%d",&k)!=EOF){
		if(k==10){
			if(flag){
				flag = 0;
			}else{
				printf("\n");
			}
			printf("93313");
		}else{
			int thief_num = k; 
			int i;
			struct linkList *p = NULL;
			for(i=k+1;;i++){
				int acc = 2;
				createLinkList(k);
				thief_num = k;
				p = head;
				while(thief_num>0){
					int eq_f = 1;
					if(acc==i){
						if(p->next->num>k){
							struct linkList *q = NULL;
							q = p->next;
							p->next = q->next;
							free(q);
							thief_num--;
							eq_f = 0;
						}else{
							break;
						}
					}
									
					acc++;
					if(acc>i){
						acc = 1;
					}
					if(eq_f){
						p = p->next;
					}
				}
				
				if(thief_num==0){
					if(flag){
						flag = 0;
					}else{
						printf("\n");
					}
					printf("%d",i);
					break;
				}
			}
		}
		
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章