点灯游戏(还没看,先留着)

来源:互联网 发布:优化电脑的软件 编辑:程序博客网 时间:2024/06/10 03:00

#include<iostream>
#include<fstream>
#include<cmath>
using namespace std;

int main()
{
     void Init(int * a,int N);
     int Value(int * a,int N);         //把数组a表示的二进制数换算成10进制
     void Add(int * a,int N);             //把数组a表示的二进制数加1
     void Change(int **p,int i, int j);
     bool check(int *p,int N);
     int N;         //表示矩阵的大小
     cout << "请输入矩阵的边长:" ;
     cin >> N;
     int **light = new int *[N];
     for(int i = 0;i<N;i++)
         light[i] = new int[N];             //动态分配二维数组light,用来存放初始值
     int **p = new int *[N];
     for(i = 0;i<N;i++)
         p[i] = new int[N];                 //动态分配二维数组p,用来存放被修改后的值
     ifstream fin;
     fin.open("data.txt");                 //**********打开文件
     for(  i = 0;i<N;i++)
         for( int j = 0;j<N;j++)
             fin >> light[i][j];             //读取数据
     fin.close();                         //**********关闭文件
     int * a = new int[N+1];
     int count;         //步数
     int mincount = (int)pow((double)2,(double)N);         //最少步数
     int **solution = new int *[N];
     for( i = 0;i<N;i++)
         solution[i] = new int[N];             //动态分配二维数组solution,用来存放解法
     int **bestsolution = new int *[N];
     for( i = 0;i<N;i++)
         bestsolution[i] = new int[N];                 //动态分配二维数组p,用来存放被最佳解法
     //!!!!!!!!!!!!!主体部分!!!!!!!!!!!!!

  for(Init(a,N);Value(a,N)<(int)pow((double)2,(double)N);Add(a,N))
     {
         for(int i = 0; i<N; i++)             //把临时数组p重置成初始值
             for(int j = 0; j<N; j++)
                 p[i][j] = light[i][j];   
    count = 0;
    for(int j = 0;j<N;j++)
    {
     solution[0][j] = a[j];
    }             //对第一行进行穷举操作
   
    for( i = 0;i<N;i++)
     for(int j = 0;j<N;j++)
      p[i][j] = light[i][j];             //把light数组复制给复本,保留原始数据值
    
     if(a[0])                 //两个if语句是对第一行的第一格和最后一格进行改动,本来可以写到循环里的,但是这样可以稍微提高点效率
     {
      p[0][0] = (p[0][0]+1)%2;         //第一行,第一个
      p[1][0] = (p[1][0]+1)%2;         //第二行,第一个
      p[0][1] = (p[0][1]+1)%2;         //第一行,第二个
     }
     if(a[N-1])
     {
      p[0][N-2] = (p[0][N-2]+1)%2;         //第一行,倒数第二个
      p[0][N-1] = (p[0][N-1]+1)%2;         //第一行,倒数第一个
      p[1][N-1] = (p[1][N-1]+1)%2;         //第二行,倒数第一个
     }
     for(j = 1;j<N-1;j++)             //对第一行的其它格子进行改动
     
     {
      if(a[j])
      {
       p[0][j] = (p[0][j]+1)%2;         //中
       p[0][j-1] = (p[0][j-1]+1)%2;     //左
       p[0][j+1] = (p[0][j+1]+1)%2;     //右
       p[1][j] = (p[1][j]+1)%2;         //下
      }
     }
     for( i = 1;i<N-1;i++)             //对第二行至第N-1行进行改动
     {
      if(!p[i-1][0])                     //两个if语句是对第i-1行的第一格和最后一格进行改动,本来可以写到循环里的,还是为了稍微提高点效率
      {
       solution[i][0] = 1;
       p[i][0] = (p[i][0]+1)%2;         //中
       p[i-1][0] = (p[i-1][0]+1)%2;     //上
       p[i+1][0] = (p[i+1][0]+1)%2;     //下
       p[i][1] = (p[i][1]+1)%2;         //右
      }
      else
       solution[i][0] = 0;
      if(!p[i-1][N-1])
      {
                 solution[i][N-1] = 1;       
     p[i][N-1] = (p[i][N-1]+1)%2;         //中
                 p[i-1][N-1] = (p[i-1][N-1]+1)%2;     //上
                 p[i+1][N-1] = (p[i+1][N-1]+1)%2;     //下
                 p[i][N-2] = (p[i][N-2]+1)%2;         //左
      }
      else
       solution[i][N-1] = 0;
      for(int j = 1;j<N-1;j++)                 //对第i-1行的其它格子进行改动
      {
       if(!p[i-1][j])
       {
        solution[i][j] = 1;
        Change(p,i,j);
       }
       else
        solution[i][j] = 0;
      }
     }
     if(!p[N-2][0])                 //两个if语句是对第N行的第一格和最后一格进行改动,本来可以写到循环里的,但是这样可以稍微提高点效率
     {
      solution[N-1][0] = 1;
      p[N-2][0] = (p[N-2][0]+1)%2;             //倒数第二行,第一个
      p[N-1][0] = (p[N-1][0]+1)%2;             //倒数第一行,第一个
      p[N-1][1] = (p[N-1][1]+1)%2;             //倒数第一行,第二个
     
     }
     else
      solution[N-1][0] = 0;
     if(!p[N-2][N-1])
     {
      solution[N-1][N-1] = 1;
      p[N-1][N-2] = (p[N-1][N-2]+1)%2;         //倒数第一行,倒数第二个
      p[N-1][N-1] = (p[N-1][N-1]+1)%2;         //倒数第一行,倒数第一个
      p[N-2][N-1] = (p[N-2][N-1]+1)%2;         //倒数第二行,倒数第一个
     }
     else
      solution[N-1][N-1] = 0;
     for( j = 1;j<N-1;j++)             //对第N行的其它格子进行改动
     {
      if(!p[N-2][j])
      {
       solution[N-1][j] = 1;
       p[N-1][j] = (p[N-1][j]+1)%2;         //中
       p[N-1][j-1] = (p[N-1][j-1]+1)%2;     //左
       p[N-1][j+1] = (p[N-1][j+1]+1)%2;     //右
       p[N-2][j] = (p[N-2][j]+1)%2;         //上
      }
      else
       solution[N-1][j] = 0;
     
     }
     if(check(p[N-1],N))             //找到解法后
     {
      cout << "解法:" << endl;
      for(int i = 0; i<N; i++)
      
      {
       for(int j = 0; j<N; j++)
       {
        count += solution[i][j];
        cout << solution[i][j] << '/t';
       }
       cout << endl;
      }
      cout << "步数为:" << count << endl;
      if(count<mincount)
      {
       mincount = count;
       for(int i = 0; i<N; i++)
        for(int j = 0; j<N; j++)
         bestsolution[i][j] = solution[i][j];
      }
     }
     cout << endl;
     }//for
 
     cout << "最佳解法为:" << endl;
     for( i = 0; i<N; i++)
     {
         for(int j = 0; j<N; j++)
         {
             count += bestsolution[i][j];
             cout << bestsolution[i][j] << '/t';
         }
         cout << endl;
     }
     cout << "最少步数为:" << mincount << endl;
     //善后工作
     delete [] a;
     for( i = 0;i<N;i++)
         delete   light[i];
     delete []light;             //将动态分配出来的light删除
 
  for( i = 0;i<N;i++)
         delete   p[i];
     delete []p;                 //将动态分配出来的p删除
 
     for( i = 0;i<N;i++)
         delete   solution[i];
     delete []solution;             //将动态分配出来的light删除
     for( i = 0;i<N;i++)
         delete   bestsolution[i];
     delete []bestsolution;                 //将动态分配出来的p删除
     system("pause");
     return 0;
}

void Init(int * a,int N)
{
 for(int  i = 0;i<=N;i++)
  a[i] = 0;
}

int Value(int * a,int N)         //把数组a表示的二进制数换算成10进制
{
 int sum = 0;
 for(int i = 0;i<=N;i++)
 {
  sum = sum + a[i]*(int)pow((double)2,(double)i);
  //cout << "sum = " << sum << endl;
 }
 return sum;
}

void Add(int * a,int N)             //把数组a表示的二进制数加1
{
 a[0]++;
 int k = 0;
 while(a[k]==2)
 {
  a[k] = 0;
  k++;
  a[k]++;
 }
}

void Change(int **p,int i, int j)
{
 p[i][j] = (p[i][j]+1)%2;
 p[i-1][j] = (p[i-1][j]+1)%2;
 p[i][j-1] = (p[i][j-1]+1)%2;
 p[i+1][j] = (p[i+1][j]+1)%2;
 p[i][j+1] = (p[i][j+1]+1)%2;
}

bool check(int *p,int N)
{
 for(int i = 0;i<N;i++)
  if(!p[i])     return false;
  return true;
}

原创粉丝点击