实现题1-4 金币阵列问题

实验目的
实现题1-4 金币阵列问题

实验原理
使用分治法,根据给定阵列初始状态,目标状态,按游戏规则计算从初始状态到目标状态需要的最少变换次数

实验步骤
①先确定某一种行变换T
②经过T变换之后我们不在进行行反转,而是进行列交换
③经过一定的列变换后观察是否和目标矩阵相同,相同则表明变换有效,得到一个变换步骤
④取步骤中的最小值

算法时间复杂度
使用了三重循环,所以为O(n^3)

实验心得
通过这次实验,我学习了如何利用分治法解决复杂的金币问题

完整代码
金币阵列

#include<cmath>
#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<ctime>
#include <fstream>
#define size 200
using namespace std;
int row; //行数
int column; //列数
int count; //交换次数
int min;
int a[size][size]; //初始矩阵
int b[size][size]; //最终矩阵
int c[size][size]; //临时存放矩阵
int found; //初始到最终是否有交换
void trans_row(int x) // 第x行取反
{
    int i;
    for (i = 0;i<column; i++)
        b[x][i] = b[x][i]^1; // 异或取反
    ::count++;
}
void trans_column(int x, int y) // 交换x和y列
{
    int i;
    int temp;
    for(i = 0; i < row; i++)
    {
        temp=b[i][x];
        b[i][x]=b[i][y];
        b[i][y]=temp;
    }
    if (x != y)
        ::count++;
}
bool same_column(int x,int y) //比较x和y列是否相同
{
    int i;
    for(i = 0; i <row; i++)
        if (a[i][x] != b[i][y])
            return 0;
    return 1;
}
void copy(int a[size][size], int b[size][size]) // 拷贝数组
{
    for (int i = 0; i <row; i++)
    for (int j = 0; j < column; j++)
        a[i][j] = b[i][j];
}
int main()
{
    
    ifstream iFile("input.txt",ios::in);
    if(!iFile)
    {
        cerr<<"open error!"<<endl;
        exit(1);
    }
    int i,j,k,p;
    int exchgmin[size];
    int num; //输入几组数据
    iFile>>num;
    for(i=0;i<num;i++)
    {
        clock_t start,end;
        start = clock();
        //计时
        
        iFile>>row;
        iFile>>column;
        for(j=0;j<row;j++)
        for(k=0;k<column;k++)
            iFile>>a[j][k];
        for(j=0;j<row;j++)
        for(k=0;k<column;k++)
            iFile>>b[j][k];
        copy(c,b); //保护原始数组b
        ::min=row+column+1;
        for(j=0;j<column;j++)
        {
            copy(b,c); //恢复原始数组b
            ::count=0;  //交换次数清零
            trans_column(0,j); //把每一列都假设成为第一列的目标状态,穷举这column中情况
            for(k=0;k<row;k++)
            { //如果行不同,则将行转换
                if(a[k][0]!=b[k][0])
                    trans_row(k);
            }
            int lo[200],flag=0,tot=0;
            for(k=0;k<column;k++)
            {//穷举其他所有列,如果相同则交换,说明目标状态统一,否则找不到与该列相同,说明不可行
                found=0;
                tot=0;flag=0;
                for(p=k;p<column;p++)
                {
                    if(same_column(k,p))
                    {
                        found=1;
                        if(p==k)
                        {break;}
                        lo[tot++]=p;
                        if(same_column(p,k))
                        {flag=1;trans_column(k,p);break;}
                    }
        
                }
                if(!found)
                    break;
                else if(!flag && tot)
                    trans_column(k,lo[0]);
            }
            if(found&&::count<::min) //如果可行,找出最小值
                ::min=::count;
        }
        if(::min<(row+column+1)) //如果交换次数比初始值小,将其保存为当前组的最小交换次数,否则不可实现交换
            exchgmin[i]=::min;
        else exchgmin[i]=-1;
        end = clock();
        printf("time=%fms",(double)(end-start)/CLK_TCK);
        ofstream out;
        out.open("output.txt");
        out<<exchgmin[i]<<endl;
        out.close();
    }
  return 0;
}

随机数生成

#include <time.h>
#include <stdlib.h>
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
	ofstream out("input_100.txt");
	out<<1<<'\n';
	out<<100<<" "<<100<<'\n';
	srand((unsigned)time(NULL));
	for(int i=0;i<200;i++)
    {
        for(int j=0;j<100;j++)
    {
        out<<rand()%2<<' ';
    }
        out<<'\n';
	}
	out.close();
	return 0;
}
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值