poj1012--鏈表和數組

一開始用單向循環鏈表來實現,提交的時候編譯錯誤,看到好多人都是類似的錯誤,可能是網站出了問題,其實即使沒問題也通不過的,當算到k=10的時候就已經很卡了。換了一種方法,用數組來實現,這下網站好了,確實還是TLE,到10的時候雖然比用鏈表要快一些,但還是卡。最後實在沒轍,看到網上有人用數學的方法,推出計算m的公式。沒仔細去看推的過程。最後只能用自己用數組實現的方法來計算出1-13對應的m值,然後打表了~~不過,這道題還是讓我運用了一下鏈表,以前都沒怎麼實際運用過。


方法一:用鏈表來實現(會超時)

#include<stdio.h>
#include<malloc.h>
#include<memory.h>

struct Node
{
	int num;
	Node *next;
};
typedef Node *ptrToNode;
typedef ptrToNode List;//指向結點的鏈表
typedef ptrToNode position;

int *excuted;

position Find(int x, List list);//查找鏈表中的元素x,返回其位置

int result[14]={0};//將已經計算過得k對應的m值保存起來,便於下次直接使用

int main()
{
	List list;
	position p,ptemp;
	int i, j, k, kk, m, count;
	
	while(1)
	{
		count = 0;
		scanf("%d", &k);
		if(k == 0)
			return 0;
		if(result[k-1]!=0)
		{
			printf("%d\n", result[k-1]);
			continue;
		}
		kk = 2*k;
		list = (Node *)malloc(sizeof(Node));
		excuted = (int *)malloc(sizeof(int)*kk);
		if(list==NULL || excuted==NULL)
		{
			printf("malloc failed!\n");
			return 1;
		}
		memset(excuted, 0, sizeof(int)*kk);
		list->num = 1;//每個結點保存每個人的編號,無頭結點
		list->next = NULL;
		for(i=2; i<=kk; i++)
		{
			p = (Node *)malloc(sizeof(Node));//爲每個結點分配空間
			if(p==NULL)
			{
				printf("malloc failed!\n");
				return 1;
			}
			p->num = i;
			//printf("%d\n", p->num);
			if(list->next==NULL)
			{
				list->next = p;
			}
			else
			{
				ptemp->next = p;
			}
			ptemp = p;
			p->next = NULL;
		}
		p->next = list;//循環鏈表
		p = list;
		/*for(i=0; i<kk; i++)
		{
			printf("%d\n", p->num);
			p = p->next;
		}*/
		m = k+1;
		p = list;
		while(count!=k)
		{
			for(i=1; i<m;)
			{
				if(excuted[p->num-1]==1)//跳過已經處死的結點
				{
					p = p->next;
				}
				else if(excuted[p->num-1]==0)
				{
					p = p->next;
					while(excuted[p->num-1]==1)
						p = p->next;
					i++;
				}
			}
			//printf("%d\n", p->num);
			if(p->num<=k)//該m不合適,恢復excuted,增加m,重新開始
			{
				memset(excuted, 0, sizeof(int)*kk);
				if(m%kk==0)
					m += k+1;
				else
				{
					m++;
					while(m%(k+1)!=0 && m%(k+1)!=1)
						m++;
				}
				count = 0;
				p = list;
			}
			else
			{
				excuted[p->num-1] = 1;
				while(1)
				{
					if(excuted[p->next->num-1]==0)
						break;
					p = p->next;
				}	
				p = p->next;
				count++; 
			}
		}
		printf("%d\n", m);
		result[k-1] = m;

		//釋放鏈表
		p = list->next;
		for(i=0; i<kk-1; i++)
		{
			ptemp = p->next;
			free(p);
			p = ptemp;
		}
		free(list);
		free(excuted);
	}
	return 0;
}


方法二:用數組來實現

#include<stdio.h>
#include<memory.h>


int num[26]={0};//保存每個人的編號
int excuted[26];//標記被處死的人,爲1表示已經被處死
int result[13]={0};//將已經計算過得k對應的m值保存起來,便於下次直接使用

int main()
{
	int i, j, k, kk, m, count,tm;
	
	while(1)
	{
		count = 0;
		scanf("%d", &k);
		if(k == 0)
			return 0;
		if(result[k-1]!=0)
		{
			printf("%d\n", result[k-1]);
			continue;
		}
		kk = 2*k;
		for(i=0; i<kk; i++)
		{
			num[i] = i+1;
		}
		m = k+1;
		j = 0;
		while(count!=k)
		{
			for(i=1; i<m;)
			{
				if(excuted[num[j]-1]==1)//跳過已經處死的結點
				{
					j++;
					if(j>=kk)//到達數組的末尾
						j=0;
				}
				else if(excuted[num[j]-1]==0)
				{
						while(1)
					{
						j++;
						if(j>=kk)//到達了數組的末尾
							j=0;
						if(excuted[num[j]-1]==0)
							break;	
					}	
					i++;
				}
			}
			//printf("%d\n", num[j]);
			if(num[j]<=k)//該m不合適,恢復excuted,增加m,重新開始
			{
				memset(excuted, 0, sizeof(int)*kk);
				if(m%kk==0)
					m += k+1;
				else
				{
					m++;
					while(m%(k+1)!=0 && m%(k+1)!=1)//m必須爲k+1的整數倍或k+1的整數倍加1,因爲當只剩下k+1個人時j必位於k或k+1的位置上
					{
						if(m%kk==0)
							m += k+1;
						else
							m++;
					}
				}
				count = 0;
				j = 0;
			}
			else
			{
				excuted[num[j]-1] = 1;
				while(1)
				{
					j++;
					if(j>=kk)//到達了數組的末尾
						j=0;
					if(excuted[num[j]-1]==0)
						break;	
				}	
				count++; 
			}
		}
		printf("%d\n", m);
		result[k-1] = m;
	}
	return 0;
}

//用上述方法能得到正確結果,但是當k到10的時候就會卡,要超時
//實在沒找到好的方法,只能先將結果算出再通過打表來輸出結果
//可以參考http://topic.csdn.net/u/20111118/13/7c4c52b4-d00b-4d4e-b52d-b9c8fdd4b24b.html
//用數學方法來推出計算m的公式
#include<stdio.h>

int result[13]={2,7,5,30,169,441,1872,7632,1740,93313,459901,1358657,2504881};//將已經計算過得k對應的m值保存起來,便於下次直接使用

int main()
{
	int k;
	
	while(1)
	{
		scanf("%d", &k);
		if(k == 0)
			break;
		else
		{
			printf("%d\n", result[k-1]);
		}
	}
	return 0;
}


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