ACM乐园
Love Me,Love My Code!
posts - 53,  comments - 24,  trackbacks - 0
算法设计与实验题解例题:金币阵列问题
问题描述:
有mxn(m <= 100,n <= 100)个金币在桌面上排成一个m行n 列的金币阵列。每一枚金
币或正面朝上或背面朝上。用数字表示金币状态,0表示金币正面朝上,1 表示背面朝上。
金币阵列游戏的规则是:
(1)每次可将任一行金币翻过来放在原来的位置上;
(2)每次可任选2 列,交换这2 列金币的位置。
算法设计:
给定金币阵列的初始状态和目标状态,计算按金币游戏规则,将金币阵列从初始状态变
换到目标状态所需的最少变换次数。


数据输入:
文件中有多组数据。文件的第1行有1 个正整数k,表示有k 组数据。每组数据的第1 行有2 个正整数m 和n。

以下的m行是金币阵列的初始状态,每行有n 个数字表示该行金币的状态,0 表示金币正面朝上,1 表示背面朝上。

接着的m行是金币阵列的目标状态。


«结果输出:
相应数据无解时输出-1。

输入文件示例
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

代码如下:

//最大变换次数不超过m+n
#include <stdio.h>
#include 
<stdlib.h>

#define swap(a,b) ((a=a+b),(b=a-b),(a=a-b))
int  table1[100][100],table2[100][100],temp[100][100],m,n,ans;//table1为初始状态,table2为目标状态

void cpy(int a[100][100],int b[100][100])//将数组b赋给数组a
{
    
for(int i=0;i<m;i++)
        
for(int j=0;j<n;j++)
            a[i][j]
=b[i][j];
}

void change1(int i)//将table1中第i行翻转
{
    
for(int j=0;j<n;j++)
        table1[i][j]
^=1;
    ans
++;
}

void change2(int i,int j)//将table1中第i列与第j列对调
{
    
if(i!=j)
    {
        
for(int k=0;k<m;k++)
        {
            swap(table1[k][i],table1[k][j]);
        }
        ans
++;
    }
}

bool same(int i,int j)//比较table2中第i列与table1中第j列是否相等
{
    
for(int k=0;k<m;k++)
        
if(table2[k][i]!=table1[k][j])
            
return false;
    
return true;
}

int main()
{
    
int t,i,j,k,best;
    
bool flag;
    scanf(
"%d",&t);
    
while(t--)
    {
        scanf(
"%d%d",&m,&n);
        
for(i=0;i<m;i++)
            
for(j=0;j<n;j++)
                scanf(
"%d",&table1[i][j]);
        
for(i=0;i<m;i++)
            
for(j=0;j<n;j++)
                scanf(
"%d",&table2[i][j]);
        best
=m+n+1;
        cpy(temp,table1);
//保存初始状态
        for(i=0;i<n;i++//枚举初始状态每一列变换为目标状态第一列的情况
        {
            
            ans
=0;
            change2(
0,i);
            
for(j=0;j<m;j++
                
if(table1[j][0]!=table2[j][0])//若此行第一列与目标第一列值不相同,则变换该行
                    change1(j);
            
for(j=1;j<n;j++//在table1中查找与table2中第j列相等的列
            {
                flag
=false//标记是否找到
                for(k=j;k<n;k++)
                    
if(same(j,k))
                    {
                        change2(j,k);
                        flag
=true;
                        
break;
                    }
                
if(flag==false)
                    
break;
            }
            
if(flag && ans<best)
                best
=ans;
            cpy(table1,temp);
            
        }
        
if(best<m+n+1)
            printf(
"%d\n",best);
        
else
            printf(
"-1\n");
    }
    
return 0;
}


 

posted on 2012-09-07 16:09 大大木马 阅读(987) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理



<2011年9月>
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

常用链接

留言簿(1)

随笔档案(53)

文章档案(2)

搜索

  •  

积分与排名

  • 积分 - 63780
  • 排名 - 351

最新评论

阅读排行榜

评论排行榜