UVa 11846 - Finding Seats Again

链接:

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2946

 

题意:

有一个 n*n(n<20)的座位矩阵里坐着k(k≤26)个研究小组。
每个小组的座位都是矩形形状。输入每个小组组长的位置和该组的成员个数,找到一种可能的座位方案。

 

分析:

深搜 + 剪枝,以矩形为搜索对象,每一层选择一个尚未放置字母的位置,作为矩形的左上角,向行和列依次扩展。

如果选择的矩形中只有一个小组,且其面积等于小组的成员个数,则在这个矩形内放置字母,然后递归下一层。

矩形的面积应不超过 9,在向列扩展的过程中可以对列的范围进行剪枝,具体见代码。

 

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 
 4 int n, k;
 5 char seat[25][25], ans[25][25];
 6 
 7 bool dfs(int id, char ch){
 8     while(ans[id/n][id%n] != '.') id++;
 9     if(id == n * n) return true;
10     int sr = id / n, sc = id % n, ec = n;
11     for(int r = sr; r < n; r++){
12         for(int c = sc; c < ec; c++){
13             if(ans[r][c] != '.') { ec = c;  break; }
14             int sum = (r - sr + 1) * (c - sc + 1);
15             if(sum > 9) { ec = c;  break; }
16             int digit = 99;
17             bool valid = true;
18             for(int t = sr; t <= r; t++){
19                 for(int i = sc; i <= c; i++){
20                     if(seat[t][i] != '.'){
21                         if(digit != 99){ valid = false;  break; }
22                         digit = seat[t][i] - '0';
23                     }
24                 }
25                 if(!valid) break;
26             }
27             if(!valid) { ec = c;  break; }
28             if(digit < sum) { ec = c;  break; }
29             if(digit > sum) continue;
30             for(int t = sr; t <= r; t++){
31                 for(int i = sc; i <= c; i++) ans[t][i] = ch;
32             }
33             if(dfs(id + c - sc + 1, ch + 1)) return true;
34             for(int t = sr; t <= r; t++){
35                 for(int i = sc; i <= c; i++) ans[t][i] = '.';
36             }
37         }
38     }
39     return false;
40 }
41 
42 int main(){
43     while(scanf("%d%d", &n, &k) && n){
44         memset(ans, '.', sizeof(ans));
45         for(int r = 0; r < n; r++) scanf("%s", seat[r]);
46         dfs(0, 'A');
47         for(int r = 0; r < n; r++){
48             for(int c = 0; c < n; c++) printf("%c", ans[r][c]);
49             printf("\n");
50         }
51     }
52     return 0;
53 }

 

总结:

搜索对象的选取很重要,若选取不当,则会运行超时。

 

posted @ 2017-12-05 04:02  Ctfes  阅读(764)  评论(0编辑  收藏  举报