hdu5113 Black And White DFS+剪枝
题意:
给你n*m的方格,你要用k种颜色去填,每种颜色要填ci次,并且要保证没有任意两个相邻的格子有相同的颜色,构造一种可行方法。
思路:
直接暴力回溯+剪枝,当没填的颜色中同种颜色数量超过(剩余格子+1)/2的时候,不可能合法。
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 #define mem(a) memset(a,0,sizeof(a)) 5 #define mp(x,y) make_pair(x,y) 6 const int INF = 0x3f3f3f3f; 7 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; 8 inline ll read(){ 9 ll x=0,f=1;char ch=getchar(); 10 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 11 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 12 return x*f; 13 } 14 ////////////////////////////////////////////////////////////////////////// 15 const int maxn = 1e5+10; 16 17 int n,m,k,c[30]; 18 int mp[10][10],flag; 19 int dx[4] = {0,0,1,-1}; 20 int dy[4] = {1,-1,0,0}; 21 22 bool ok(int x,int y,int col){ 23 for(int i=0; i<4; i++){ 24 int tx=x+dx[i],ty=y+dy[i]; 25 if(tx<0 || tx>=n || ty<0 || ty>=m) continue; 26 if(mp[tx][ty] == col) return false; 27 } 28 return true; 29 } 30 31 void dfs(int sta){ 32 if(flag) return ; 33 if(sta == n*m){ 34 flag = true; 35 puts("YES"); 36 for(int i=0; i<n; i++){ 37 for(int j=0; j<m; j++){ 38 cout << mp[i][j]; 39 if(j==m-1) cout << endl; 40 else cout << " "; 41 } 42 } 43 return ; 44 } 45 46 int ma=-1; 47 for(int i=1; i<=k; i++) ma = max(ma,c[i]); 48 if(ma>(n*m-sta+1)/2) return ; 49 50 int x=sta/m,y=sta%m; 51 for(int i=1; i<=k; i++){ 52 if(c[i]==0) continue; 53 if(ok(x,y,i)){ 54 mp[x][y] = i; 55 c[i]--; 56 dfs(sta+1); 57 mp[x][y] = -1; 58 c[i]++; 59 } 60 } 61 } 62 63 int main(){ 64 int T=read(); 65 for(int cas=1; cas<=T; cas++){ 66 memset(mp,-1,sizeof(mp)); 67 flag = 0; 68 n=read(),m=read(),k=read(); 69 for(int i=1; i<=k; i++) 70 c[i] = read(); 71 cout << "Case #" << cas << ":\n"; 72 dfs(0); 73 if(!flag) puts("NO"); 74 } 75 76 return 0; 77 }