地图的四着色 (CSU-1508)
描述
有一個(gè)R行C列的網(wǎng)格地圖,每個(gè)國家是一個(gè)四連通區(qū)域。你的任務(wù)是用紅,綠,藍(lán),黃四種顏色給地圖著色,使得相鄰國家的顏色不同。
一個(gè)人著色比較無趣,所以你想請女朋友陪你一起涂——你涂紅綠,她涂藍(lán)黃。當(dāng)然,紳士是不會(huì)讓讓女朋友受累的,所以她最多只需涂5個(gè)國家(恰好5個(gè)也行)。
你的任務(wù)是統(tǒng)計(jì)有多少種著色的方法。注意,每個(gè)顏色都至少要用一次。
輸入
輸入包含不超過100組數(shù)據(jù)。每組數(shù)據(jù)第一行為兩個(gè)整數(shù)R和C (1<=R,C<=20),即網(wǎng)格的行數(shù)和列數(shù)。以下R行每行C個(gè)大寫字母。相同字母所組成的四連通區(qū)域代表一個(gè)國家。輸入保證國家數(shù)目不超過30,并且大多數(shù)測試點(diǎn)的國家數(shù)都比較小。
輸出
對于每組數(shù)據(jù),輸出測試點(diǎn)編號和著色方案數(shù)。
樣例輸入
2 4
AABB
BBAA
1 5
ABABA
4 7
AABAABB
ABBCCCB
BBAACBB
CCABBAC
樣例輸出
Case 1: 24
Case 2: 144
Case 3: 3776
思路:
以樣例一為例
首先將給出的字符數(shù)組尋找連通塊,將每個(gè)四連通的相同字母的每一塊進(jìn)行標(biāo)號
即:AABB 轉(zhuǎn)變?yōu)?:0011
? ? ? ?BBAA? ? ? ? ? ? ? ? ?2233
然后進(jìn)行縮點(diǎn),將每一塊編號相同的區(qū)域作為以這個(gè)編號的結(jié)點(diǎn),構(gòu)建鄰接矩陣,即如果一個(gè)編號的四連通區(qū)域有其他編號,就說明這兩個(gè)點(diǎn)連通
即有:0110
? ? ? ? ? ?1001
? ? ? ? ? ?1001
? ? ? ? ? ?0110
此時(shí)有了鄰接矩陣后,可以直接搜索進(jìn)行染色以統(tǒng)計(jì)方案數(shù),但由于數(shù)據(jù)范圍過大因此會(huì)超時(shí),考慮剪枝
假設(shè)男性使用 A、B 兩個(gè)顏色涂色,女性使用 C、D 兩個(gè)顏色涂色,此時(shí)男性、女性的涂色順序有四種:AB|CD、AB|DC、BA|CD、BA|DC
由于無論哪個(gè)顏色先涂,結(jié)果最終都是等價(jià)的,因此規(guī)定男性使用的第一個(gè)顏色是 A,女性使用的第一個(gè)顏色是 C,然后進(jìn)行搜索,最終求出來的 res 是結(jié)果的 1/4,因此最終答案為 res*4
源程序
#include<iostream> #include<cstdio> #include<cstdlib> #include<string> #include<cstring> #include<cmath> #include<ctime> #include<algorithm> #include<utility> #include<stack> #include<queue> #include<vector> #include<set> #include<map> #include<bitset> #define EPS 1e-9 #define PI acos(-1.0) #define INF 0x3f3f3f3f #define LL long long const int MOD = 1E9+7; const int N = 2000+5; const int dx[] = {-1,1,0,0,-1,-1,1,1}; const int dy[] = {0,0,-1,1,-1,1,-1,1}; using namespace std; int n,m; char mp[N][N];//字符矩陣 int grade[N][N];//連通塊標(biāo)號 int G[N][N];//鄰接矩陣 int colors[N]; void dfs(int x,int y,int num){//尋找連通塊記錄標(biāo)號grade[x][y]=num;for(int i=0;i<4;i++){int nx=x+dx[i];int ny=y+dy[i];if(nx<0||nx>=n||ny<0||ny>=m)continue;if(mp[x][y]==mp[nx][ny]&grade[nx][ny]==-1)dfs(nx,ny,num);} } void buildMap(int num){//建立鄰接矩陣for(int x=0;x<m;x++){for(int y=0;y<num;y++){for(int k=0;k<4;k++){int nx=x+dx[k];int ny=y+dy[k];if(nx<0||ny<0||nx>=num||ny>=num)continue;if(grade[x][y]!=grade[nx][ny]){int nodeX=grade[x][y];int nodeY=grade[nx][ny];G[nodeX][nodeY]=1;G[nodeY][nodeX]=1;}}}} } bool judge(int step,int color,int num){for(int i=0;i<num;i++)if(G[step][i]==1&&colors[i]==color)return false;return true; } int dye(int step,int A,int B,int C,int D,int num){//染色int res=0;if(step==num){if(A!=0&&B!=0&&C!=0&&D!=0)res++;return res;}if(judge(step,0,num)){colors[step]=0;res+=dye(step+1,A+1,B,C,D,num);}if(A&&judge(step,1,num)){colors[step]=1;res+=dye(step+1,A,B+1,C,D,num);}if(C+D<5&&judge(step,2,num)){colors[step]=2;res+=dye(step+1,A,B,C+1,D,num);}if(C&&C+D<5&&judge(step,3,num)){colors[step]=3;res+=dye(step+1,A,B,C,D+1,num);}colors[step]=-1;return res; } int main(){int Case=1;while(scanf("%d%d",&n,&m)!=EOF){for(int i=0;i<n;i++){getchar();for(int j=0;j<m;j++)scanf("%c",&mp[i][j]);}//尋找連通塊,并進(jìn)行標(biāo)號memset(grade,-1,sizeof(grade));int num=0;for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(grade[i][j]==-1){dfs(i,j,num++);}}}//建立鄰接矩陣memset(G,0,sizeof(G));buildMap(num);//染色memset(colors,-1,sizeof(colors));int res=dye(0,0,0,0,0,num);printf("Case %d: %d\n",Case++,res*4);}return 0; }?
總結(jié)
以上是生活随笔為你收集整理的地图的四着色 (CSU-1508)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: string matching(HDU-
- 下一篇: Uim的情人节礼物·其之弐(洛谷-P25