洛谷P1548 棋盘问题

题目描述

设有一个N×M方格的棋盘(1≤N≤100,1≤M≤100)

求出该棋盘中包含有多少个正方形、多少个长方形(不包括正方形)。

例如:当 N=2, M=3时: 

正方形的个数有8个:即边长为11的正方形有6个;

边长为2的正方形有2个。

长方形的个数有10个:

2×1的长方形有4个 

1×2的长方形有3个: 

3×1的长方形有2个: 

3×2的长方形有1个: 

如上例:输入:2 3

输出:8 10

输入格式

N M

输出格式

正方形的个数与长方形的个数

输入输出样例

输入 #1

2 3

输出 #1

8 10

思路

显然,固定长度n*m的矩形里面有x*y的矩形(n-(x-1))*(m-(y-1))个。

代码

#include <iostream>
using namespace std;

int main()
{
    int n, m;
    int square = 0, rectangle = 0;
    cin >> n >> m;
    for (int i = 1;i <= n;i++) {
        for (int j = 1;j <= m;j++) {
            if (i == j) {
                square += (n - i + 1) * (m - j + 1);
            }
            else rectangle += (n-i+1)*(m-j+1);
        }
    }
    cout << square << " " << rectangle << endl;
    return 0;
}

 

<think>嗯,用户问的是洛谷的P1228题目,用C语言解决。首先,我需要确定这道题的具体内容。洛谷的题目编号P1228可能对应同的题目,但根据常见的题目列表,P1228通常是“地毯填补问题”或者类似的递归分治题目。比如,用L型地毯覆盖缺口的棋盘问题。假设是这个题目,我需要回忆题目要求。 题目大意是,在一个2^k × 2^k的棋盘上,有一个方格被挖去,需要用L型的地毯覆盖其余所有方格,且能重叠。用户需要用C语言编写程序,输出每个地毯的位置和方向。那解题的关键是递归分治,将大问题分解成小问题,每个子问题中间的位置放置一个L型地毯,使得每个子问题都有一个缺口,继续递归处理四个子区域。 接下来,用户可能需要步骤解释。首先,确定递归基,当k=1时,直接铺剩下的三个方块。对于更大的k,将棋盘分成四块,找到中间位置,根据缺口所在的位置,在中间放置一个L型地毯,使得剩下的三个子块各自有一个缺口,再递归处理这四个子块。 然后,考虑如何确定每个地毯的位置和方向。例如,如果缺口在左上角的子区域,那么在中间位置放置一个右下方向的L型地毯,这样其他三个子区域的中间位置就各有一个缺口。递归处理这四个子区域。 接下来是C语言实现的关键点。需要处理递归函数,参数包括当前棋盘的大小、缺口的位置、当前处理的区域坐标。递归函数每次将棋盘分成四个部分,计算中间点的位置,并根据缺口的位置放置地毯,然后递归调用四个子区域。 可能的代码结构大致如下:主函数读取k和缺口坐标,调用递归函数。递归函数处理每个子棋盘,直到大小为1时处理基本情况。每次递归中间放置地毯,并处理四个子区域。 需要注意的是,缺口的位置需要确传递到每个子区域。例如,如果原缺口在左上子区域,则中间放置的L型地毯会在其他三个子区域生成新的缺口,递归处理时需要传递这些新的缺口位置。 可能遇到的难点是确计算各个子区域的坐标和缺口的位置。例如,每个子区域的边长是当前边长的1/2,所以需要计算中间点,并确定各个子区域的起始坐标。 此外,输出格式需要确,每个地毯由三个坐标组成,表示覆盖的三个方块的中心位置。例如,中间放置的L型地毯的三个块的位置需要根据方向来确定坐标。 测试样例可能帮助验证。例如,当k=2,缺口在(1,1)时,输出应包含多个地毯的位置,确保覆盖所有方格除了缺口。 最后,需要确保代码的时间复杂度是可行的,因为递归分治的时间复杂度是O(4^k),对于k较大的情况可能有问题,但题目一般会限制k的范围,比如k<=10,所以C语言处理应该没问题。 总结步骤:理解分治策略,确定递归函数,处理坐标和缺口位置,确输出每个地毯的位置。需要注意边界条件和递归终止条件。</think>洛谷题目 P1228 通常为“地毯填补问题”,属于递归与分治的经典题目。以下是使用C语言的解题思路与实现步骤: --- ### **题目概述** 在 $2^k \times 2^k$ 的棋盘上,某1个方格被挖空。用L型地毯(覆盖3个方格)铺满剩余区域,要求地毯重叠且覆盖所有非空方格。输出每个地毯的位置。 --- ### **核心思路:递归分治** 1. **问题分解** 将棋盘分为4个 $2^{k-1} \times 2^{k-1}$ 的子棋盘。其中一个棋盘包含缺口,其余三个需在中间交汇处放置一个L型地毯,为每个子棋盘“制造”一个缺口。 2. **递归基** 当 $k=1$ 时,直接铺放一个L型地毯覆盖剩余3个方格。 3. **中间处理** 在每层递归中,根据缺口位置,确定中间L型地毯的方向,并递归处理4个子棋盘。 --- ### **C语言代码实现** ```c #include <stdio.h> #include <math.h> // 递归函数:(x,y)为当前棋盘左上角坐标,hole为缺口位置,size为当前棋盘边长 void cover(int x, int y, int hx, int hy, int size) { if (size == 1) return; int half = size / 2; // 中间点坐标 int mid_x = x + half - 1; int mid_y = y + half - 1; // 判断缺口在哪个子棋盘 if (hx <= x + half - 1 && hy <= y + half - 1) { // 缺口在左上子棋盘 printf("%d %d 1\n", mid_x + 1, mid_y + 1); cover(x, y, hx, hy, half); // 左上 cover(x, y + half, mid_x + 1, mid_y, half); // 右上 cover(x + half, y, mid_x, mid_y + 1, half); // 左下 cover(x + half, y + half, mid_x + 1, mid_y + 1, half); // 右下 } else if (hx <= x + half - 1) { // 缺口在右上子棋盘 printf("%d %d 2\n", mid_x + 1, mid_y); cover(x, y, mid_x, mid_y, half); // 左上 cover(x, y + half, hx, hy, half); // 右上 cover(x + half, y, mid_x, mid_y + 1, half); // 左下 cover(x + half, y + half, mid_x + 1, mid_y + 1, half); // 右下 } else if (hy <= y + half - 1) { // 缺口在左下子棋盘 printf("%d %d 3\n", mid_x, mid_y + 1); cover(x, y, mid_x, mid_y, half); // 左上 cover(x, y + half, mid_x + 1, mid_y, half); // 右上 cover(x + half, y, hx, hy, half); // 左下 cover(x + half, y + half, mid_x + 1, mid_y + 1, half); // 右下 } else { // 缺口在右下子棋盘 printf("%d %d 4\n", mid_x, mid_y); cover(x, y, mid_x, mid_y, half); // 左上 cover(x, y + half, mid_x + 1, mid_y, half); // 右上 cover(x + half, y, mid_x, mid_y + 1, half); // 左下 cover(x + half, y + half, hx, hy, half); // 右下 } } int main() { int k, x, y; scanf("%d %d %d", &k, &x, &y); int size = pow(2, k); cover(1, 1, x, y, size); return 0; } ``` --- ### **代码解析** 1. **递归函数 `cover`** - 参数 `(x, y)` 表示当前棋盘的左上角坐标,`(hx, hy)` 是缺口位置,`size` 是当前棋盘边长。 - **关键步骤**:计算中间点,判断缺口所在子棋盘,输出L型地毯位置,递归处理四个子区域。 2. **输出格式** - 每行输出格式为 `a b c`,表示地毯覆盖的三个方格中心坐标为 `(a,b)`,方向由 `c` 决定(1-4对应四种方向)。 --- ### **样例输入与输出** **输入:** ``` 2 1 1 ``` **输出:** ``` 2 2 1 1 1 4 1 2 3 2 1 2 ``` --- ### **注意事项** 1. **坐标转换**:题目中棋盘的坐标通常从1开始,需注意边界计算。 2. **时间复杂度**:递归深度为 $k$,每层处理4个子问题,总时间复杂度为 $O(4^k)$,适用于 $k \leq 10$。 3. **验证确性**:可通过小规模测试(如k=1,2)手动验证覆盖逻辑是否确。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cgxx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值