c语言:金币阵列的问题_C 语言

  有m*n(m <=100,n <=100)个金币在桌面上排成一个m行n 列的金币阵列。每一枚金币或正面朝上或背面朝上。用数字表示金币状态,0表示金币正面朝上,1 表示背面朝上。

  金币阵列游戏的规则是: (1)每次可将任一行金币翻过来放在原来的位置上;

  (2)每次可任选2 列,交换这2 列金币的位置。

   编程任务:给定金币阵列的初始状态和目标状态,编程计算按金币游戏规则,将金币阵列从初始状态变换到目标状态所需的最少变换次数。

Input

  输入数据有多组数据。第1行有1 个正整数k,表示有k 组数据。每组数据的第1 行有2 个正整数m 和n。以下的m行是金币阵列的初始状态,每行有n 个数字表示该行金币的状态,0 表示金币正面朝上,1 表示背面朝上。接着的m行是金币阵列的目标状态。

Output

  将计算出的最少变换次数按照输入数据的次序输出。相应数据无解时输出-1。

代码是别人的,感觉写的很好。写这个博客,主要是想要重温一下思路。

枚举1~m中,每一列为第一列的情况,

//从1~n行,找出不满足的行,进行一次行变换

//若是所枚举的这一列可以成功根据规则转换成目标矩阵,则,此时的矩阵与原矩阵的差别只会在列序上

此时,从i=2 列(第二列)开始与目标矩阵的第i列进行比较,

若不同,寻找本矩阵中第j列(就= i+1~m)是否有与目标矩阵的第i列相同的,若有,且 本矩阵第j列!= 目标矩阵第j列,则,进行一次列变换

//若是找不到符合条件的列,则所枚举的这一列为第一列是不可能按所给规则变换到目标矩阵的

复制代码 代码如下:

#include<stdio.h>

 const int inf = 99999;
 const int N = 101;

 int a[N][N],b[N][N],temp[N][N]; //a存储初始矩阵,b为目标状态矩阵
 int n,m;
 int need;//需要变换次数

 void ChangeL(int x,int y)//变换列
 {
     if(x==y)return;
     int i;
     for(i=1;i<=n;i++)
     {
         int tt=temp[i][y];
         temp[i][y]=temp[i][x];
         temp[i][x]=tt;
     }
     need++;
 }

 void ChangeH(int x)//变换行
 {
     int i;
     for(i=1;i<=m;i++)
     {
         temp[x][i]^=1;
     }
 }

 bool Same(int x,int y) //判断列是否满足条件
 {
     int i;
     for(i=1;i<=n;i++)
         if(b[i][x]!=temp[i][y])return false;
     return true;
 }

 int main()
 {
     int tests;
     scanf("%d",&tests); //数据组数

     while(tests--)
     {
         scanf("%d%d",&n,&m); //n行,m列
         int i,j;
         for(i=1;i<=n;i++)
             for(j=1;j<=m;j++)
             {
                 scanf("%d",&a[i][j]);
             }

             for(i=1;i<=n;i++)
                 for(j=1;j<=m;j++)
                     scanf("%d",&b[i][j]);

             int k;
             int ans=inf; //ans存储最终答案,初始值为无穷大

 
             for(k=1;k<=m;k++)//枚举各列为第一列
             {
                 for(i=1;i<=n;i++)
                     for(j=1;j<=m;j++)
                         temp[i][j]=a[i][j];
                 need=0;
                 ChangeL(1,k);

 
                 //不满足的行,进行一次变换
                 for(i=1;i<=n;i++)
                 {
                     if(temp[i][1]!=b[i][1])//该行不满足条件
                     {
                         ChangeH(i);//变换行
                         need++;
                     }
                 }

                 bool find;
                 for(i=1;i<=m;i++)//检查每列是否满足条件
                 {
                     find=false;
                     if(Same(i,i))
                     {
                         find=true;
                         continue;
                     }
                     for(j=i+1;j<=m;j++)//寻找temp中与b的i列相同的列
                     {
                         if(Same(i,j))//temp 的 j列于b的i列相同
                         {
                             if(Same(j,j))continue;//temp的j列与b的j列相同
                             ChangeL(i,j);//交换temp的i,j列
                             find=true;
                             break;
                         }
                     }
                     if(find==false)//找不到该列对应列
                     {
                         break;
                     }
                 }

                 if(find==true&&need<ans)
                     ans=need;
             }

             if(ans<inf)
                 printf("%d\n",ans);
             else
                 printf("-1\n");
     }
     return 0;
 }

时间: 2024-09-16 08:42:54

c语言:金币阵列的问题_C 语言的相关文章

C语言金币阵列问题解决方法_C 语言

本文实例详细讲述了C语言实现金币阵列问题的解决方法,分享给大家供大家参考.具体方法如下: 问题描述: 有m*n(1 ≤ m, n ≤ 100)个金币在桌面上排成一个 m 行 n 列的阵列.每一枚金币或正面朝上或背面朝上.用数字表示金币状态,0表示金币正面朝上,1 表示背面朝上. 金币阵列游戏的规则是: 1. 每次可将任一行金币翻过来放在原来的位置上: 2. 每次可任选 2 列,交换这 2 列金币的位置. 本题要求对于给定的金币阵列初始状态和目标状态,编程计算按金币游戏规则,将金币阵列从初始状态变

C语言指针入门学习面面观_C 语言

这似乎是一个很凝重的话题,但是它真的很有趣. 1. 指针是指向某一类型的东西,任何一个整体,只要能称为整体就能拥有它自己的独一无二的指针类型,所以指针的类型其实是近似无穷无尽的 2. 函数名在表达式中总是以函数指针的身份呈现,除了取地址运算符以及sizeof 3. C语言最晦涩难明的就是它复杂的声明: void (*signal(int sig, void (*func)(int)))(int),试试着把它改写成容易理解的形式 4. 对于指针,尽最大的限度使用const保护它,无论是传递给函数,

C语言实现程序开机自启动_C 语言

程序比较简单,用到了C语言获得自身路径和系统路径,修改注册表项等,某些函数不理解可以查看MSDN #include<stdio.h> #include<windows.h> char *GetFilename(char *p) //得到一个路径的纯文件名 { int x=strlen(p); char ch='\\'; char *q=strrchr(p,ch); return q; } int main() { char *filepath; char modlepath[256

C语言冒泡排序算实现代码_C 语言

冒泡排序是排序算法的一种,思路清晰,代码简洁,常被用在大学生计算机课程中. "冒泡"这个名字的由来是因为越大的元素会经由交换慢慢"浮"到数列的顶端,故名. 这里以从小到大排序为例进行讲解. 基本思想及举例说明 冒泡排序的基本思想就是不断比较相邻的两个数,让较大的元素不断地往后移.经过一轮比较,就选出最大的数:经过第2轮比较,就选出次大的数,以此类推. 下面以对 3  2  4  1 进行冒泡排序说明. 第一轮 排序过程3  2  4  1    (最初) 2  3 

C语言单链表的实现_C 语言

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素. 链表结构: SList.h #pragma once typedef int DataType; typedef struct SListNode { DataType data; struct SListNode* next; }SListNode; // 如果要修改链表就必须加引用 SListNode* _BuyNode(DataType x); //建立节点 void PrintSlist(SListNode

模拟实现C语言中的内存管理_C 语言

这里模拟了C语言中的内存管理,当我们要创建或者使用一个对象时,那么这个对象会调用retain方法,计数+1,当我们要释放对象,我们会调用free,这里注意要对计数记性判断,如果是0的话,那么就会销毁. #import <Foundation/Foundation.h> int cnt = 0; void fun (charchar * p) { printf("%c\n",p[0]); } charchar * retain1(charchar * p) { //retai

linux下基于C语言的信号编程实例_C 语言

本文实例讲述了linux下基于C语言的信号编程方法.分享给大家供大家参考.具体如下: #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> void sig_handler(int sig_no, siginfo_t *info, void *ctext){ printf("receive si

C语言读写配置文件的方法_C 语言

本文实例讲述了C语言读写配置文件的方法.分享给大家供大家参考.具体如下: CException.h如下: /************************************************************************/ /* make0000@msn.com */ /************************************************************************/ /***********************

C语言时间处理实例分享_C 语言

一.简介 时间处理在编程中经常遇到,包括程序的运行时间和显示时间等.在标准C中, 日期和时间的处理包含在 time.h 的头文件中,需要使用日期和时间相关的类型的函数的话, 需要导入time.h. 二.实例 1.计算时差 #include <stdio.h> #include <sys/time.h> #include <unistd.h> int main() { struct timeval start, end; unsigned long spend_time;