[BFS]翻幣問題

翻幣問題

Description

有N個硬幣(6<=N<=20000)全部正面朝上排成一排,每次將其中5個硬幣翻過來放在原位置,直到最後全部硬幣翻成反面朝上爲止。試編程找出步數最少的翻法,輸出最少步數及翻法。


Input

從鍵盤輸入一個正整數N(6<=N<=20000),表示硬幣的數量。


Output

第1行:一個整數,表示最少步數
第2行至最後一行:先是一個整數,表示步驟序號(從0開始編號),後接一個":",再接當前硬幣的狀態(用一個整數表示正面朝上的硬幣的個數)


Sample Input

6


Sample Output

6


解析

任意翻轉5個硬幣,正反面的個數變化爲:
5正0反 正-5 反+5
4正1反 正-3 反+3
3正2反 正-1 反+1
2正3反 正+1 反-1
1正4反 正+3 反-3
0 正5反 正+5 反-5
即有6種變化,用state[i]表示節點i正面的個數,完成翻轉即正面的個數爲0,在執行上面6種翻轉時要檢查是否符合翻條件,即正面的個數和反面的個數要大於其對應的翻轉數,生成新節點時要判斷此節點是否出現過,否則就會出現相同的5個硬幣翻來翻去的情況。


代碼

#include<stdio.h>
#include<iostream>
using namespace std;
int n,a[20005],fa[20005],t[20005],ans[20005];
void bfs(){
	int head=0,tail=1;
	a[1]=n;fa[1]=0;ans[1]=0;
	do{
		head++; 
		for(int i=0;i<=5;i++){ //六種可能
			if(a[head]>=i and n-a[head]>=5-i){ //條件判斷
				tail++;
				ans[tail]=ans[head]+1;
				a[tail]=a[head]-i+5-i;
				fa[tail]=head;
				if(!t[a[tail]])t[a[tail]]=1; //如果沒翻過,就標記
				 else tail--; 
				 if(a[tail]==0){
					printf("%d",ans[tail]);
					return ;
				}
			}
		}
	}while(head<=tail);
}
int main(){
	scanf("%d",&n);
	bfs();
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章