1 条题解

  • 0
    @ 2026-9-23 18:22:06

    自认为代码写的比较优雅。

    思路

    这道题要求把 R×CR \times C 个拼图块放入网格中。每个拼图块可以旋转,因此对于每个拼图块,需要枚举它的 44 种方向。

    我们按照从上到下、从左到右的顺序依次填格子。

    对于每块拼图,我们检查它与上方和左方已经填好的拼图(或是边缘)是否合法即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=105;
    struct Node
    {
        int id;char e[4];
    }p[N],g[15][15];
    int R,C,n;
    bool vis[N];
    bool check(int x, int y, char e[4]) 
    {
        if (x == 1 and e[0] != '0') return false;
        if (x == R and e[2] != '0') return false;
        if (y == 1 and e[3] != '0') return false;
        if (y == C and e[1] != '0') return false;
        
        if (x > 1 and g[x - 1][y].e[2] != e[0]) return false;
        if (y > 1 and g[x][y - 1].e[1] != e[3]) return false;
        
        return true;
    }
    bool dfs(int x,int y)
    {
        if(x>R )return true;
        int nx=y==C?x+1:x;
        int ny=y==C?1:y+1;
        for(int i=1;i<=n;i++)
        {
            if(vis[i])continue;
            vis[i]=true;
            char cur[4];
            for(int k=0;k<4;k++)cur[k]=p[i].e[k];
            for(int k=0;k<4;k++)
            {
                if(check(x,y,cur))
                {
                    g[x][y].id=p[i].id;
                    for(int j=0;j<4;j++)g[x][y].e[j]=cur[j];
                    if(dfs(nx,ny))return true;
                }
                rotate(cur,cur+3,cur+4);
            }vis[i]=false;
        }return false;
    }
    
    int main()
    {
        cin.tie(0)->sync_with_stdio(0);
    
        cin>>R>>C;n=R*C;
        for(int i=1;i<=n;i++)
        {
            cin>>p[i].id;
            for(int j=0;j<4;j++)cin>>p[i].e[j];
        }
        dfs(1,1);
    
        for (int i = 1; i <= R; i++) 
        {
            for (int j = 1; j <= C; j++) 
            {
                cout << g[i][j].id << " " 
                     << g[i][j].e[0] << " " << g[i][j].e[1] << " " 
                     << g[i][j].e[2] << " " << g[i][j].e[3] << "\n";
            }
        }
        return 0;
    }
    

    std::rotate 的作用

    std::rotate 是 C++ STL 中非常强大且优雅的一个算法函数,专门用来处理数组、vector 等序列的循环左移操作。

    它的基本用法和参数含义非常直观。可以把它想象成:把一个序列变成一个环,然后转动一段距离,再重新切开。

    函数原型

    std::rotate(first, middle, last);
    

    它接收三个迭代器或指针作为参数:

    • first:指向需要旋转的序列开头。
    • middle:指向旋转后新序列第一个元素的位置。
    • last:指向序列的结尾,也就是最后一个元素的下一个位置,符合 STL 左闭右开的原则,即 [first,last)[first,last)。

    执行逻辑

    std::rotate 会把 [middle,last)[middle,last) 这一段区间的元素整体移动到序列的最前面,把原来的 [first,middle)[first,middle) 这一段区间的元素整体移动到序列的末尾。

    复杂度

    最坏情况下会枚举拼图块的排列和旋转,复杂度为 O(n!⋅4n)O(n! \cdot 4^n)。但本题数据中边缘字母较多,匹配限制很强,搜索可以很快剪枝。

    • 1

    信息

    ID
    846
    时间
    1000ms
    内存
    128MiB
    难度
    5
    标签
    递交数
    21
    已通过
    13
    上传者