二维平面深度优先-POJ 1020 Anniversary Cake
Posted 一米阳光213
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二维平面深度优先-POJ 1020 Anniversary Cake相关的知识,希望对你有一定的参考价值。
思路分析:
AC 代码: 16 ms
// 思路:这个问题没有巧妙的思路,于是只有贪心:能放下就放下,凑失败了就换一个。
// 将大蛋糕人为划分为 SIZE * SIZE 个小格子,然后“从上到下,从左到右”依次填充大蛋糕。
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
/*************** 全局变量 ******************/
char G[42][42];
int SIZE, n; // 大蛋糕尺寸为 SIZE * SIZE,小蛋糕有 n 个
int cases; // 测试用例的数量
int a[18]; // 所有小蛋糕的边长
bool visit_a[18]; // 所有小蛋糕被使用的情况
int col[42]; // 记载每一列被占用的格子数
bool visit_map[18]; // 所有小蛋糕被使用的情况,是否被使用了
bool is_OK; // 本问题是否可解
bool cmp(int a, int b)
return a > b;
int min(int a, int b)
return a > b ? b : a;
// used_cakes: 已经使用的小蛋糕数量
// col 是核心的数据,描述了当前大蛋糕被填充的情况
//
void dfs(int used_cakes)
// Step 1: Termination condition
if (used_cakes == n || is_OK == true)
is_OK = true;
return;
// Step 2: 确定搜索范围
// 根据剪枝1,从前往后选
for (int i = 0; i < n && is_OK==false; i++)
// Step 3: 排除无效的候选对象
if (visit_a[i] == true) continue;
// 从前往后找,找某一列其占用格子数最少
// 坑:要找首次出现的占用格子数最少的列,所以,搜索的顺序应该是从后往前找,或者判断条件为 < 而不是 <= (细节)
int min_ind = -1, min_val = 999999;
for (int j = 0; j <SIZE; j++)
if (col[j] < min_val)
min_ind = j;
min_val = col[j];
if ( SIZE - col[min_ind] < a[i] || min_ind + a[i] -1 >= SIZE || col[min_ind+a[i]-1] != col[min_ind] )
continue; // 为了加速程序,此处快速判断
int w_x = 0; // 水平方向能容纳的最大宽度
int w_y = 0; // 垂直方向能容纳的最大宽度
int w = 0; // 综合来看,当前能容纳的最大宽度
for (int j = min_ind; j < SIZE;j++)
if (col[j] <= min_val)
w_x++;
else
break;
w_y = SIZE - col[min_ind];
w = min(w_x, w_y);
// 判断是否能放得下
if (a[i] > w) continue;
// Step 4: 访问当前结点(即,使用当前小蛋糕)
visit_a[i] = true;
int new_val = col[min_ind] + a[i];
for (int j = min_ind; j <= min_ind + a[i] - 1; j++)
col[j] += a[i]; // 之所以不是 col[j] += a[i],是考虑到了像俄罗斯方块一样,前一层有缺口
// Step 5: 继续下一步的搜索
dfs(used_cakes + 1);
if (is_OK == true) return;
// Step 6: 放弃使用当前这个小蛋糕!
for (int j = min_ind; j <= min_ind + a[i] - 1; j++)
col[j] -= a[i];
visit_a[i] = false;
// used_cakes: 已经使用的小蛋糕数量
// col 是核心的数据,描述了当前大蛋糕被填充的情况
//
void dfs_fast(int used_cakes)
// Step 1: Termination condition
if (used_cakes == n || is_OK == true)
is_OK = true;
return;
// Step 2: 确定搜索范围
// 剪枝:如果尺寸为 x 的蛋糕,导致了失败,则后面跳过所有尺寸为 x 的蛋糕
int failure_size = -1;
for (int i = 0; i < n && is_OK == false; i++)
// Step 3: 排除无效的候选对象
if (visit_a[i] == true || a[i] == failure_size) continue;
// 从前往后找,找某一列其占用格子数最少
// 坑:要找首次出现的占用格子数最少的列,所以,搜索的顺序应该是从后往前找,或者判断条件为 < 而不是 <= (细节)
int min_ind = -1, min_val = 999999;
for (int j = 0; j <SIZE; j++)
if (col[j] < min_val)
min_ind = j;
min_val = col[j];
if (SIZE - col[min_ind] < a[i] || min_ind + a[i] - 1 >= SIZE || col[min_ind + a[i] - 1] != col[min_ind])
continue; // 为了加速程序,此处快速判断
int w_x = 0; // 水平方向能容纳的最大宽度
int w_y = 0; // 垂直方向能容纳的最大宽度
int w = 0; // 综合来看,当前能容纳的最大宽度
for (int j = min_ind; j < SIZE; j++)
if (col[j] <= min_val)
w_x++;
else
break;
w_y = SIZE - col[min_ind];
w = min(w_x, w_y);
// 判断是否能放得下
if (a[i] > w) continue;
// Step 4: 访问当前结点(即,使用当前小蛋糕)
visit_a[i] = true;
int new_val = col[min_ind] + a[i];
for (int j = min_ind; j <= min_ind + a[i] - 1; j++)
col[j] += a[i]; // 之所以不是 col[j] += a[i],是考虑到了像俄罗斯方块一样,前一层有缺口
// Step 5: 继续下一步的搜索
dfs_fast(used_cakes + 1);
if (is_OK == true)
return;
else if (used_cakes == 0)
return;
else
failure_size = a[i];
// Step 6: 放弃使用当前这个小蛋糕!
for (int j = min_ind; j <= min_ind + a[i] - 1; j++)
col[j] -= a[i];
visit_a[i] = false;
int main(int argc, char * argv[])
cin >> cases;
while (cases--)
/*************** Input ****************/
// Initialization
memset(G, 0, sizeof(G));
memset(a, 0, sizeof(a));
memset(visit_a, 0, sizeof(G));
memset(col, 0, sizeof(col));
is_OK = false;
// Input
int area = 0;
int num_big_cakes = 0;
scanf("%d%d", &SIZE, &n);
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
area += a[i] * a[i];
if (a[i] > SIZE / 2) num_big_cakes++;
if (area != SIZE * SIZE || num_big_cakes > 1)
cout << "HUTUTU!" << endl;
continue;
// Sort
sort(a, a + n, cmp);
/*************** Process ****************/
dfs_fast(0);
/*************** Output ****************/
if (is_OK)
cout << "KHOOOOB!" << endl;
else
cout << "HUTUTU!" << endl;
return 0;
以上是关于二维平面深度优先-POJ 1020 Anniversary Cake的主要内容,如果未能解决你的问题,请参考以下文章
[深度优先搜索] POJ 1426 Find The Multiple
[深度优先搜索] POJ 3620 Avoid The Lakes
LeetCode 1020 飞地的数量[dfs] HERODING的LeetCode之路
图论DFS(Depth First Search)Algorithm深度优先搜索遍历空间平面图选择路径,networkx,Python