洛谷题单指南-递推与递归-P1228 地毯填补问题

原题链接:https://www.luogu.com.cn/problem/P1228

题意解读:用4种毯子铺满2^k * 2^k的区域,留出一个公主位置,输出所有毯子拐角的坐标以及哪种毯子,看起来有点无从下手,

可以从k=1,k=2,k=3入手去依次考虑,找到规律,用分治法解决。

解题思路:

1、当k=1时,即2*2的区域,对于任意一个位置是公主,都可以得到唯一一种铺设方案

2、当k=2时,即4*4的区域,对于任意一个位置是公主,如下图:

可以将4*4区域划分成4个2*2的区域

如果每个区域都有一个公主,问题就好解决了,因为右上区域有了公主,可以假设最中间的2*2区域的右上角有公主,先对这个区域进行铺设:

然后,把中间铺设的地毯都当做公主,这样就能保证4个2*2的区域都有了公主:

再分4个区域依次进行处理,问题就变成了k=1时的情况,即可得到上图的结果。

3、同理,当k=3时,即8*8的区域,对于任意位置是公主,如下图:

将8*8区域划分成4个4*4区域

根据公主所在的区域,对中间2*2区域进行铺设

这样,假设中间2*2铺设的毯子都是公主,则4个4*4区域就都有了公主

再依次对4个4*4区域进行处理,问题就变成了k=2时的情况,最终可以变成k=1时的情况,问题得解。

100分代码:

#include <bits/stdc++.h>
using namespace std;

int k, x, y;

//cover是铺地毯函数,(x1,y1)是左上角的坐标,(x2,y2)是右下角的坐标,(x,y)是公主的的坐标
void cover(int x1, int y1, int x2, int y2, int x, int y)
{
    if(x2 - x1 == 1) //2 * 2区域时
    { 
        //公主在左上角,用毯子1
        if(x1 == x && y1 == y) cout << x2 << " " << y2 << " " << 1 << endl; 
        //公主在右上角,用毯子2
        else if(x1 == x && y2 == y) cout << x2 << " " << y1 << " " << 2 << endl;
        //公主在左下角,用毯子3
        else if(x2 == x && y1 == y) cout << x1 << " " << y2 << " " << 3 << endl;
        //公主在右下角,用毯子4
        else cout << x1 << " " << y1 << " " << 4 << endl;

        return;
    }

    //将2^k * 2^k区域分成4个2^(k-1) * 2^(k-1)的区域
    //计算公主在哪个区域,把正中间的2*2区域用一个地毯覆盖,这个地毯相当于让4个2^(k-1) * 2^(k-1)的区域都有一个公主
    //再递归处理

    int len = x2 - x1 + 1; //len是边长
    int half = len / 2; //half是边长的一半

    //中间2 * 2区域每个格子的坐标
    int xa = x1 + half - 1, ya = y1 + half - 1; //左上
    int xb = x1 + half - 1, yb = y1 + half; //右上
    int xc = x1 + half, yc = y1 + half - 1; //左下
    int xd = x1 + half, yd = y1 + half; //右下

    //公主在左上区域
    if(x >= x1 && x <= xa && y >= y1 && y <= ya) 
    {
        //填补正中间2*2区域
        cover(xa, ya, xd, yd, xa, ya);
        //设定左上区域的公主位置
        xa = x, ya = y;
    }
    //公主在右上区域
    else if(x >= x1 && x <= xb && y >= yb && y <= y2)
    {
        //填补正中间2*2区域
        cover(xa, ya, xd, yd, xb, yb);
        //设定右上区域的公主位置
        xb = x, yb = y;
    }
    //公主在左下区域
    else if(x >= xc && x <= x2 && y >= y1 && y <= yc)
    {
        //填补正中间2*2区域
        cover(xa, ya, xd, yd, xc, yc);
        //设定左下区域的公主位置
        xc = x, yc = y;
    }
    //公主在右下区域
    else 
    {
        //填补正中间2*2区域
        cover(xa, ya, xd, yd, xd, yd);
        //设定右下区域的公主位置
        xd = x, yd = y;
    }

    //递归处理4个2^(k-1) * 2^(k-1)的区域
    cover(x1, y1, x1 + half - 1, y1 + half - 1, xa, ya); //左上
    cover(x1, y1 + half, x1 + half - 1, y2, xb, yb);  //右上
    cover(x1 + half, y1, x2, y1 + half - 1, xc, yc);  //左下
    cover(x1 + half, y1 + half, x2, y2, xd, yd); //右下
}

int main()
{
    cin >> k >> x >> y;
    cover(1, 1, 1 << k, 1 << k, x, y);
    return 0;
}

 

posted @ 2024-02-21 17:35  五月江城  阅读(196)  评论(0编辑  收藏  举报