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;
}
相关推荐
stolentime10 小时前
CF2066D1 Club of Young Aircraft Builders (easy version)题解
c++·算法·动态规划·组合数学
Dillon Dong10 小时前
【风电控制】高低穿现场失败的原因分析——算法简单但工程复杂
算法·变流器·风电控制·dfig
小欣加油11 小时前
leetcode41 缺失的第一个正数
数据结构·c++·算法·leetcode
I Promise3411 小时前
智驾APA_HPA可行驶区域检测算法工程师面试问题整理可参考
算法·面试·职场和发展
智者知已应修善业11 小时前
【51单片机按键控制1分钟正计时倒计时暂停复位】2024-1-2
c++·经验分享·笔记·算法·51单片机
weixin_4684668511 小时前
UNet 模型结构从零搭建与实战解析
人工智能·深度学习·算法·机器学习·ai·unet
努力努力再努力wz11 小时前
【Qt入门系列】一文掌握 Qt 常用显示类控件:QLCDNumber、QProgressBar 与 QCalendarWidget
c语言·开发语言·数据结构·数据库·c++·git·qt
Useasy_JIJIANYUN11 小时前
合作快讯:极简云呼叫中心(Useasy)正式上架Zoho全球应用市场!
算法
isyoungboy11 小时前
Delaunay 拓扑图割法一种特征抽稀算法
算法
Shan120512 小时前
算法案例精讲:连接所有点的最小费用
算法