2016藍橋杯省賽第七題剪郵票

qq_43318301發表於2020-10-03

剪郵票

這是本人第一次寫部落格,希望大家多多支援!
如【圖1.jpg】, 有12張連在一起的12生肖的郵票。

在這裡插入圖片描述

現在你要從中剪下5張來,要求必須是連著的。(僅僅連線一個角不算相連)

比如,【圖2.jpg】,【圖3.jpg】中,粉紅色所示部分就是合格的剪取。

在這裡插入圖片描述
在這裡插入圖片描述

請你計算,一共有多少種不同的剪取方法。

請填寫表示方案數目的整數。

注意:你提交的應該是一個整數,不要填寫任何多餘的內容或說明性文字。

答案:116

思路:本來一開始準備用全排列做的,結果發現嚴重超時,轉而思考dfs,也就是用最標準的dfs模板,但是要注意的一個點是邊界的處理,所以我們把1到12換成了1,2,3,4,6,7,8,9,11,12,13,14,便於處理,上程式碼:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int num[20];
int vis[20];
int temp[]={1,2,3,4,6,7,8,9,11,12,13,14};//這一步至關重要 
int step[4]={-5,-1,1,5};
int ans;
void dfs(int index)
{
	if(index==5){
		int flag1=1;
		int flag2=0;
		for(int i=0;i<5;i++){
			if(vis[num[i]-1]==0&&vis[num[i]+1]==0&&vis[num[i]-5]==0&&vis[num[i]+5]==0){
				flag1=0;
			}
		}
		int count=0;
		for(int i=0;i<5;i++){
			for(int j=0;j<4;j++){
				if(vis[num[i]-step[j]]==1){
					count+=1;
				}
			}
		}
		if(count>6){
			flag2=1;
		}
		if(flag1==1&&flag2==1){
			ans+=1;
		}
		return;	
	}
	for(int i=0;i<12;i++){
		if(vis[temp[i]]==0){
			num[index]=temp[i];
			vis[temp[i]]=1;
			dfs(index+1);
			vis[temp[i]]=0;
		}
	}
}
int main(){
	ans=0;
	memset(vis,0,sizeof(vis));
	dfs(0);
	cout << ans/120 << endl;
	return 0;
}

如有錯誤,歡迎批評指正!

相關文章