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;
    }
    
    
  • 相关阅读:
    mysql 基础学习2
    mysql 基础学习1
    awk 截取某段时间的日志
    Kinaba 简单画图
    ELK系统分析Nginx日志并对数据进行可视化展示
    ELK日志分析平台搭建全过程
    python linecache模块读取文件的方法
    python windows 远程执行bat
    PHP常用函数封装
    OneinStack 安装
  • 原文地址:https://www.cnblogs.com/AWCXV/p/11616757.html
Copyright © 2011-2022 走看看