UVA-11846 找座位 题解答案代码 算法竞赛入门经典第二版

GitHub - jzplp/aoapc-UVA-Answer: 算法竞赛入门经典 例题和习题答案 刘汝佳 第二版

题目有两种思考方式:

  1. 遍历队长,对每个队长生成可能的矩形,递归所有情况看看能不能得到结果。

  2. 直接遍历整个正方形的所有座位。对这个座位放到一个矩形中,如果这个矩形符合要求(内部包含一个队伍且没有重叠),则递归遍历。

方案1超时,方案2最后AC了。可能是因为方案1重复遍历的次数太多。

这里还是想提一下方案1的代码,一开始我将整个正方式所有座位表示出来,如果上面有队伍就设置对应位置为队伍序号。对于一个新的队伍,尝试所有可行的矩形排列。在每个矩形排列中,遍历所有座位看有没有重叠。

后面我优化了方案,不遍历所有座位了,而是将问题转化为这个矩形和已有的队伍矩形比较,看有没有重叠。方案是看两个矩形的中心距离有没有超过边长/2。(虽然最后还是超时)

最后方案2的AC代码如下:

cpp 复制代码
#include <stdio.h>
#include <string.h>

int arr[35][35];
int n, k;

struct Group
{
  int x, y;
  int num;
  bool hasFind;
};

// 下标从1开始
Group groups[30] = {};
int glen;

bool computed(int index);

// 判断单个矩形是否符合要求
bool judgeRect(int xmin, int ymin, int xmax, int ymax)
{
  int i, j;
  for (i = xmin; i <= xmax; ++i)
  {
    for (j = ymin; j <= ymax; ++j)
    {
      if (arr[i][j])
        return false;
    }
  }
  return true;
}

// 对矩形设置值
void setRect(int xmin, int ymin, int xmax, int ymax, int v)
{
  int i, j;
  for (i = xmin; i <= xmax; ++i)
    for (j = ymin; j <= ymax; ++j)
      arr[i][j] = v;
}

int judgeTeam(int xmin, int ymin, int xmax, int ymax)
{
  int i, j;
  int index = -1;
  for (i = 1; i < glen; ++i)
  {
    if (groups[i].hasFind)
      continue;
    if (groups[i].x >= xmin && groups[i].x <= xmax && groups[i].y >= ymin && groups[i].y <= ymax)
    {
      if (index != -1)
        return -1;
      index = i;
    }
  }
  if (index == -1)
    return index;
  if (groups[index].num != (xmax - xmin + 1) * (ymax - ymin + 1))
    return -1;
  return index;
}

bool computed(int x, int y)
{
  if (x >= n)
    return true;
  if (y >= n)
    return computed(x + 1, 0);
  if (arr[x][y])
    return computed(x, y + 1);
  int i, j;
  int t;
  for (i = x; i < n; ++i)
  {
    for (j = y; j < n; ++j)
    {
      if (!judgeRect(x, y, i, j))
        continue;
      t = judgeTeam(x, y, i, j);
      if (t <= 0)
        continue;
      groups[t].hasFind = true;
      setRect(x, y, i, j, t);
      if (computed(x, y + 1))
        return true;
      setRect(x, y, i, j, 0);
      groups[t].hasFind = false;
    }
  }
  return false;
}

void output()
{
  int i, j;
  int groupMap[30] = {};
  int gi = 0;
  for (i = 0; i < n; ++i)
  {
    for (j = 0; j < n; ++j)
    {
      if (!groupMap[arr[i][j]])
        groupMap[arr[i][j]] = ++gi;

      printf("%c", groupMap[arr[i][j]] + 'A' - 1);
    }
    putchar('\n');
  }
}

int main()
{
  int i, j, kt;
  char c;
  while (scanf("%d %d", &n, &k) == 2 && n > 0 & k > 0)
  {
    memset(groups, 0, sizeof(groups));
    memset(arr, 0, sizeof(arr));
    glen = 0;
    kt = 1;
    for (i = 0; i < n; ++i)
    {
      getchar();
      for (j = 0; j < n; ++j)
      {
        c = getchar();
        if (c != '.')
        {
          groups[kt] = {i, j, c - '0', false};
          ++kt;
        }
      }
    }
    glen = kt;
    if (!computed(0, 0))
    {
      printf("xxx\n");
      continue;
    }
    output();
  }
  return 0;
}
相关推荐
秋天的怀念_David3 小时前
第二十一夜 · 数字黑洞与西西弗斯的惩罚
java·程序人生·算法
碧海银沙音频科技研究院4 小时前
在PC电脑上用Whisper→Marian算法实现离线语音翻译功能
算法·whisper
niyongsheng4 小时前
3D 装箱算法工程化:数据结构、放置启发式与支撑规则
数据结构·算法·rust
叉烧滑蛋6 小时前
B站台湾大学郭彦甫|MATLAB 学习笔记|04 变量与档案存取
数据结构
j7~7 小时前
【穷举、深搜与回溯算法】一棵决策树讲透全排列与子集
数据结构·c++·算法·leetcode·回溯·递归
傅科摆 _ py8 小时前
DP,贪心,堆和栈,二分力扣复习
开发语言·python·算法
Shaoshing8 小时前
LeetCode100 42.接雨水
java·算法·leetcode
域限奇点访客9 小时前
用AI生成问卷的网站怎么选?看题目录入结构、题型映射和生成后的校验
算法
not coder10 小时前
一文讲通--从树到红黑树
数据结构·算法
octopus_c10 小时前
C++ 入门
开发语言·c++·算法