zoukankan      html  css  js  c++  java
  • 【1-4】金币阵列问题

    问题描述:
    有m ´ n(m £ 100,n £ 100) 个金币在桌面上排成一个m 行 n 列的金币阵列。每一枚金
    币或正面朝上或背面朝上。用数字表示金币状态,0 表示金币正面朝上,1 表示背面朝上。
    金币阵列游戏的规则是:
    (1)每次可将任一行金币翻过来放在原来的位置上;
    (2)每次可任选 2 列,交换这 2 列金币的位置。
    ´编程任务:
    给定金币阵列的初始状态和目标状态,编程计算按金币游戏规则,将金币阵列从初始状
    态变换到目标状态所需的最少变换次数。
    ´数据输入:
    由文件 input.txt 给出输入数据。文件中有多组数据。文件的第 1 行有 1 个正整数 k,表
    示有 k 组数据。每组数据的第 1 行有 2 个正整数 m 和 n。以下的 m 行是金币阵列的初始状
    态,每行有 n 个数字表示该行金币的状态,0 表示金币正面朝上,1 表示背面朝上。接着的
    m 行是金币阵列的目标状态。
    ´结果输出:
    将计算出的最少变换次数按照输入数据的次序输出到文件 output.txt。相应数据无解时
    输出-1。
    输入文件示例 输出文件示例
    input.txt output.txt
    2
    4 3
    1 0 1
    0 0 0
    1 1 0
    1 0 1
    1 0 1
    1 1 1
    0 1 1
    1 0 1
    4 3
    1 0 1
    0 0 0
    1 0 0
    1 1 1
    1 1 0
    1 1 1
    0 1 1
    1 0 1
    2
    -1

    【题解】

    我们假定最后的答案中a数组中的第j列和b数组中的第一列相同 那么我们就先用行取反操作真的把a数组中的第j列变成和b数组的第一列一样。 这个时候你会发现,你再也不能用行取反操作了. 只剩下列交换操作可以用了。 那么只需要把b数组和a数组变成n个列向量(用字符串表示),然后把两个数组都按照字符串排个序就好(字符串的字典序). 如果两个字符串数组完全相同,那么就可以从a变换到b 记录下a的第i列要换到b的第几列就可以了。 然后就变成另外一个问题了: 已知位置i上的数字最后要到next[i]位置。只能进行交换操作,问最少要操作几次才能满足所有的i(1<=i<=n) 这个个经典问题了,最后会形成若干个环,∑(环的大小-1)就是操作步骤了,再加上之前取反操作的次数就是a的第j列和b的第一列相同的情况下的答案了

    【代码】

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    
    struct abc{
        string s;
        int column;
    };
    
    const int N = 100;
    
    int T,m,n;
    int a[N+10][N+10],b[N+10][N+10];
    abc bcs[N+10];
    int aa[N+10][N+10];
    int minstep = -1;
    
    bool cmp(abc a,abc b){
        return a.s<b.s;
    }
    
    void fz(int r){
        for (int i = 1;i <= n;i++){
            aa[r][i] = 1-aa[r][i];
        }
    }
    
    
    
    int judge(int idx){
    
        int step = 0;
        for (int i = 1;i <= m;i++){
            if (aa[i][idx]!=b[i][1]){
                fz(i);
                step++;
            }
        }
        //把aa的每一列看成一个长度为m的01字符串,即n个字符串
        abc acs[N+10];
        int nex[N+10];//记录aa的每一列需要变换到哪一列
        for (int j = 1;j <= n;j++){
            string temp = "";
            for (int i = 1;i <= m;i++){
                temp = temp + (char)(aa[i][j]+'0');
            }
            acs[j].column = j;
            acs[j].s = temp;
        }
        sort(acs+1,acs+1+n,cmp);
        //for (int i = 1;i <= n;i++) cout<<acs[i].s<<" ";cout<<endl;
        //for (int i = 1;i <= n;i++) cout<<bcs[i].s<<" ";
        //exit(0);
        for (int i = 1;i <= n;i++)
            if (acs[i].s!=bcs[i].s)
                return -1;
            else {
                nex[acs[i].column] = bcs[i].column;
            }
        int flag[N+10];
        for (int i = 1;i <= n;i++) flag[i] = -1;
        for (int i = 1;i <= n;i++)
            if (flag[i]==-1){
                int j = i;
                int cnt = 0;
                while (flag[j]==-1){
                    flag[j] = 1;
                    cnt++;
                    j = nex[j];
                }
                step+=cnt-1;
            }
        return step;
    }
    
    int main(){
        //freopen("E://tran5.in","r",stdin);
        cin >> T;
        while (T--){
            minstep = -1;
            cin >> m >> n;
            for(int i = 1;i <= m;i++)
                for (int j = 1;j <= n;j++)
                    cin >> a[i][j];
            for(int i = 1;i <= m;i++)
                for (int j = 1;j <= n;j++)
                    cin >> b[i][j];
            //将b转换成n个列向量
            for (int j = 1;j <= n;j++){
                string temp="";
                for (int i = 1;i <= m;i++){
                    temp = temp + (char)(b[i][j]+'0');
                }
                bcs[j].s = temp;
                bcs[j].column = j;
            }
            sort(bcs+1,bcs+1+n,cmp);
    
            for (int j = 1;j <= n;j++){//suppose j column equal to first column of b
                memcpy(aa,a,sizeof(a));
                int t = judge(j);
                if (t==-1) continue;
                if (minstep==-1){
                    minstep = t;
                }else minstep = min(minstep,t);
            }
            cout<<minstep<<endl;
        }
        return 0;
    }
    
    
  • 相关阅读:
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 88怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 81.0怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 40怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 24.0怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 21.0怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下驱动器试运行提示过速度保护怎么办
    倍福TwinCAT(贝福Beckhoff)基础教程 松下驱动器如何执行绝对值清零
    倍福TwinCAT(贝福Beckhoff)基础教程 松下绝对值驱动器如何做初始化设置
    倍福TwinCAT(贝福Beckhoff)基础教程 松下官方软件开启报错伺服未就绪怎么办
    JAVA Eclipse 启动 Eclipse 弹出“Failed to load the JNI shared library jvm_dll”怎么办
  • 原文地址:https://www.cnblogs.com/AWCXV/p/11616757.html
Copyright © 2011-2022 走看看