HDU 5113 Black And White 回溯+剪枝
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5113
Black And White
Memory Limit: 512000/512000 K (Java/Others)
输入
The first line contains only one integer T (1 ≤ T ≤ 5000), which indicates the number of test cases.
For each test case, the first line contains three integers: N, M, K (0 < N, M ≤ 5, 0 < K ≤ N × M ).
The second line contains K integers ci (ci 0), denoting the number of cells where the i-th color should be used.
It’s guaranteed that c1 + c2 + · · · + cK = N × M .
输出
For each test case, the first line contains “Case #x:”, where x is the case number (starting from 1).
In the second line, output “NO” if there is no coloring satisfying the requirements. Otherwise, output “YES” in one line. Each of the following N lines contains M numbers seperated by single whitespace, denoting the color of the cells.
If there are multiple solutions, output any of them.
样例输入
4
1 5 2
4 1
3 3 4
1 2 2 4
2 3 3
2 2 2
3 2 3
2 2 2
样例输出
Case #1:
NO
Case #2:
YES
4 3 4
2 1 2
4 3 4
Case #3:
YES
1 2 3
2 3 1
Case #4:
YES
1 2
2 3
3 1
题意
给你n*m的方格,你要用k种颜色去填,每种颜色要填ci次,并且要保证没有任意两个相邻的格子有相同的颜色,构造一种可行方法,如果不存在输出-1.
题解
直接暴力回溯+剪枝,当没填的颜色中同种颜色数量超过(剩余格子+1)/2的时候,不可能合法。
代码
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf
typedef int LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII;
const int INF=0x3f3f3f3f;
const LL INFL=10000000000000000LL;
const double eps=1e-9;
const double PI = acos(-1.0);
//start----------------------------------------------------------------------
const int maxn=33;
int n,m,k;
int arr[maxn];
int mat[7][7];
bool su;
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
bool ok(int x,int y,int color){
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(mat[nx][ny]==color) return false;
}
return true;
}
void dfs(int sta){
if(sta==n*m){
su=true;
prf("YES\n");
rep(i,0,n){
rep(j,0,m){
prf("%d",mat[i][j]);
if(j==m-1) prf("\n");
else prf(" ");
}
}
return;
}
///剪枝
int ma=0;
for(int i=1;i<=k;i++) ma=max(ma,arr[i]);
if(ma>(n*m-sta+1)/2) return;
///回溯
int x=sta/m,y=sta%m;
for(int i=1;i<=k;i++){
if(arr[i]==0) continue;
if(ok(x,y,i)){
mat[x][y]=i;
arr[i]--;
dfs(sta+1);
if(su) return;
arr[i]++;
mat[x][y]=-1;
}
}
}
void init(){
clr(mat,-1);
}
int main() {
int tc,kase=0;
scf("%d",&tc);
while(tc--) {
init();
scf("%d%d%d",&n,&m,&k);
for(int i=1;i<=k;i++){
scf("%d",&arr[i]);
}
prf("Case #%d:\n",++kase);
su=false;
dfs(0);
if(!su) prf("NO\n");
}
return 0;
}
//end-----------------------------------------------------------------------