1 条题解

  • 1
    @ 2026-8-11 23:12:13

    非官解(仅供参考)(新手第一次写题解求大佬放过) 数据量 1<=n<=10 非常少了 O(n!) 就能过。 我这里提供一个**O(n^3)**的比较好写和理解的解

    #include<bits/stdc++.h>
    using namespace std;
    int x[11][11][11],y[11][11][11];
    int main(){
        int n,b,cntm=10000;
        //输入与初始化
        cin>>n;
        for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){
            cin>>b;
            x[i][j][b]=1;
            y[i][j][b]=1;
            for(int k=1;k<=n;k++)if(!y[k][j][b])y[k][j][b]=2;
            for(int k=1;k<=n;k++)if(!x[i][k][b])x[i][k][b]=2;
        }
        //枚举可能结果并计数
        for(int k=1;k<=n;k++){
            //按列枚举
            for(int i=1;i<=n;i++){
                int cnt=0;
                for(int j=1;j<=n;j++){
                    if(x[j][i][k]==2)cnt++;
                    else if(x[j][i][k]==0)cnt+=2;
                }
                if(cnt<cntm)cntm=cnt;
            }
            //按行枚举
            for(int i=1;i<=n;i++){
                int cnt=0;
                for(int j=1;j<=n;j++){
                    if(y[i][j][k]==2)cnt++;
                    else if(y[i][j][k]==0)cnt+=2;
                }
                if(cnt<cntm)cntm=cnt;
            }
        }
        cout<<cntm;
        return 0;
    }
    

    我们如何形成一个解?

    3 1 2 1

    1 3 4 2

    3 2 2 3

    4 1 4 4

    假如我想要一个第一行全是1的解我们需要将下面的两个1移动上来,一个1直接上移一个1先右移后上移共需要1+2=3步。

    我们可以发现一个空位同一列内有1则最少需要1步。同一列没有1则一定最少需要2步。不是空位则最少需要0步。

    题目要求要最少的移动次数。我们只需要枚举所有的解并做上述统计取其中最少的即可。如果直接写则是**O(n^4)**比较大而且不好写。

    我这里通过x[i][j][k]和y[i][j][k]来存储我们想要的信息并通过初始化来降低时间复杂度

    x[1][1][1]==1意思是(1,1)格存在1

    x[1][1][1]==2意思是(1,1)格没一但所在行存在1

    x[1][1][1]==0则是(1,1)格上面两种都不满足

    y[i][j][k]同理只不过==2时是所在列

    这样就可以同过直接遍历x,y数组来获取我们所有解的移动次数

    • 1

    信息

    ID
    1476
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    (无)
    递交数
    4
    已通过
    2
    上传者