您的位置:首页 > 其它

金币阵列问题

2015-09-09 16:36 309 查看
问题描述:
有m x 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
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

output.txt
2

-1

2015年9月21日:
#include<malloc.h>
#include<iostream>
#include<fstream>

#define INF 1<<30

using namespace std;
/*将矩阵a的第col行进行行变换*/
void transfer_row(int array[],int n)
{
int i=0;
for(i=0;i<n;i++)
array[i]^=1;
}

/*交换矩阵a的i和j列*/
void swap_columns(int **a,int m,int n,int i,int j)
{
int k=0;
while(k<m)
{
int tmp=a[k][i];
a[k][i]=a[k][j];
a[k][j]=tmp;
k++;
}
}

/*比较矩阵a的第col_a列和矩阵b的第col_b列是否相等*/
int compare_column(int **a,int **b,int m,int n,int col_a,int col_b)
{
int k=0;
for(k=0;k<m;k++)
{
if(a[k][col_a]!=b[k][col_b])
return 0;
}
return 1;
}

/*将矩阵src的内容复制到矩阵dest中*/
void copy_array(int** dest,int **src,int m,int n )
{
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
dest[i][j]=src[i][j];
}

/**寻找将原始矩阵a变换到目标矩阵b的最少变换次数,如果不能将a变换到b,那么返回-1*/
int find(int **a,int **b,int m,int n)
{
/**flag记录一次变换,是否能够达到目标矩阵*/
int flag=0;

/**best为最少交换次数,初始值为无穷大*/
int best=INF;

/**count记录一次变换过程中需要进行交换的次数*/
int count=0;

int **tmp=(int **)malloc(sizeof(int *)*m);
int i=0;
for(i=0;i<m;i++)
tmp[i]=(int *)malloc(sizeof(int)*n);

copy_array(tmp,a,m,n);

/*以列变换为基准,一次将初始矩阵a的每一列与第一列交换*/
for(i=0;i<n;i++)
{
swap_columns(a,m,n,i,0);
if(i!=0)
count++;
//int j=0;
/*列变换后,将a的新的第一列和目标矩阵b的第一列比较,
若a中第一列中某行元素与b中第一列相应行的元素不相等,则将a中该行进行变换
完成此过程后,a的第一列元素和b的第一列元素完全相同,下面列变换过程中就不能再进行行变换!
*/
for(int j=0;j<m;j++)
{
if(a[j][0]!=b[j][0])
{
transfer_row(a[j],n);
count++;
}
}

//int k=0;
/**从a中一次寻找相应的某些列使得这些列一次和b中的第2到第n列相等,
如果查找成功,则说明此种变换可以达到目标状态,然后将此种变换所花费的变换次数和当前最有变换次数best比较
如果小于best,则将best更新此种变换的花费的变换次数
*/
for(int j=1;j<n;j++)
{
flag=0;
for(int k=j;k<n;k++)
{
if(compare_column(a,b,m,n,k,j))  // 比较a的第k列和b的第j列是否相等
{
if(k!=j)
{
count++;
swap_columns(a,m,n,k,j); // 如果a与目标状态b的相同列的位置不一样就对a进行列变换
}
flag=1;         // 每次如果a中有与b这一列相同的列就直接置flag为1然后跳出循环
break;
}
}
if(flag==0)
break;
//count=0;
}
if(flag==1&&best>count)
best=count;
count=0;
copy_array(a,tmp,m,n);
}
if(best<INF)
return best;
else
return -1;
}

int main()
{
ifstream in("input.txt");
int m,n;
cin>>m>>n;
int **a=(int **)malloc(sizeof(int*)*m);
int **b=(int **)malloc(sizeof(int*)*m);
for(int i=0;i<m;i++)
{
a[i]=(int *)malloc(sizeof(int)*n);
b[i]=(int *)malloc(sizeof(int)*n);
}

for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
cin>>a[i][j];
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
cin>>b[i][j];

int res=find(a,b,m,n);
cout<<res<<endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: