Question:http://poj.org/problem?id=1020
问题点:DFS。
1 Memory: 260K Time: 47MS
2 Language: C++ Result: Accepted
3
4 #include <iostream>
5 using namespace std;
6
7 int mat[40];//按列记录小块Cake填充状态
8 int side[16];//小块Cake边长
9 bool visit[16];//小块Cake是否已使用
10 int width,cnt;//大块Cake边长 小块Cake数量
11 bool flag;//是否能被填充标志
12 int cmp(const void* a,const void* b)
13 {
14 return *(int*)b - *(int*)a;//降序排列
15 }
16 //状态更新: pn为1时,从x列开始填充第idx块Cake,并判断是否能填充进去
17 // pn为-1时,从x列开始清除第idx块Cake
18 bool update(int idx,int x,int pn)
19 {
20 int i,temp = mat[x];
21 if(pn == 1)
22 {
23 //填充第idx块Cake后,长宽不能超过边界
24 if(side[idx] + x > width || mat[x] + side[idx] > width) return false;
25 //判断x列到x+side[idx]-1列 是否同高度
26 for(i=1;i<side[idx];i++)
27 {
28 if(temp != mat[x+i]) return false;
29 }
30 visit[idx] = true;
31 }
32 else
33 {
34 visit[idx] = false;
35 }
36 for(i=0;i<side[idx];i++)
37 {
38 mat[x+i] += side[idx]*pn;
39 }
40 return true;
41 }
42 //获取当前最小高度处的最小列,填充顺序为"从低到高,从左到右"
43 int getLowX()
44 {
45 int i,temp=100;
46 for(i=0;i<width;i++)
47 {
48 temp =(temp<mat[i]?temp:mat[i]);
49 }
50 for(i=0;i<width && temp!= mat[i];i++);
51 return i;
52 }
53 //idx为已填充数 ,x为小块Cake编号
54 void dfs(int idx,int x)
55 {
56 if(idx == cnt) {//当全部填充完毕时,返回true
57 flag = true;
58 return;
59 }
60 for(int i=0,w=0;i<cnt;i++)
61 {
62 if(visit[i]) continue;//已填充的不再填充
63 if(w == side[i]) continue; else w = side[i];//同边长的不重复填充
64 if(update(i,x,1))//在x列填充第i块Cake
65 {
66 dfs(idx+1,getLowX());
67 if(flag) return;
68 update(i,x,-1);//在x列清除第i块Cake
69 }
70 }
71 }
72 int main()
73 {
74 int eg;
75 cin>>eg;
76 while(eg--)
77 {
78 int i,j,k;
79 memset(mat,0,sizeof(mat));
80 memset(side,0,sizeof(side));
81 memset(visit,0,sizeof(visit));
82 flag = false;
83 cin>>width;
84 cin>>cnt;
85 for(i=0;i<cnt;i++)
86 {
87 cin>>side[i];
88 }
89 qsort(side,cnt,sizeof(int),cmp);//排序用于去重
90 dfs(0,0);
91 if(flag) cout<<"KHOOOOB!"<<endl;
92 else cout<<"HUTUTU!"<<endl;
93 }
94 //system("pause");
95 return 0;
96 }