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;
}
相关推荐
开开心心就好2 小时前
免费好用:PPT演示计时提醒工具
windows·计算机视觉·计算机外设·逻辑回归·excel·深度优先·csdn开发云
米粒12 小时前
力扣算法刷题 Day 31 (贪心总结)
算法·leetcode·职场和发展
少许极端2 小时前
算法奇妙屋(四十)-贪心算法学习之路7
java·学习·算法·贪心算法
AlenTech3 小时前
647. 回文子串 - 力扣(LeetCode)
算法·leetcode·职场和发展
py有趣3 小时前
力扣热门100题之合并两个有序链表
算法·leetcode·链表
8Qi83 小时前
LeetCode热题100--45.跳跃游戏 II
java·算法·leetcode·贪心算法·编程
foundbug9993 小时前
基于STM32的步进电机加减速程序设计(梯形加减速算法)
stm32·单片机·算法
东北甜妹4 小时前
MYSQL 总结
数据结构
北顾笙9804 小时前
day12-数据结构力扣
数据结构·算法·leetcode