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;
}
相关推荐
Dlrb12117 小时前
C语言-指针数组与数组指针
c语言·数据结构·算法·指针·数组指针·指针数组·二级指针
WL_Aurora8 小时前
Python 算法基础篇之集合
python·算法
平行侠8 小时前
A15 工业路由器IP前缀高速检索与内存压缩系统
网络·tcp/ip·算法
阿旭超级学得完9 小时前
C++11包装器(function和bind)
java·开发语言·c++·算法·哈希算法·散列表
li星野9 小时前
位运算 & 数学 & 高频进阶九题通关(Python + C++)
c++·python·学习·算法
jerryinwuhan9 小时前
hello算法,简单讲(1)
算法·排序算法
y = xⁿ9 小时前
20天速通LeetCodeday15:BFS广度优先搜索
算法·宽度优先
400分9 小时前
吃透RAG核心-----语义检索与关键字检索底层原理
算法·架构
目黑live +wacyltd9 小时前
算法备案:常见驳回原因与应对策略
人工智能·算法
磊 子10 小时前
多态类原理+四种类型转换+异常处理
开发语言·c++·算法