Manchester


私信TA

用户名:wenyajie

访问量:331913

签 名:

在历史前进的逻辑中前进,这个逻辑就是人心向背的逻辑

等  级
排  名 1
经  验 65524
参赛次数 1
文章发表 188
年  龄 0
在职情况 学生
学  校 Xiamen University
专  业 计算机科学

  自我简介:

在历史前进的逻辑中前进,这个逻辑就是人心向背的逻辑

解题思路:
1.假设二维数组为  N=3

0   1   2    H=0  代表行:第一行 

3   4   5    H=1

6   7   8    H=2

H=3,没有这行,结束;

注意:以下程序使用了一维数组代替二维数组:(因为刚开始用全排列做的,一维数组直接把全排列搬过来就可,之后换方法就没改)

每一行的第一个元素,在一维数组中的下标为[H*N];

每行的最后一个元素,在一位数组中的下表为[H*N+N-1],即:[(H+1)*N-1]

 以下是递归关系:(得到所有不同矩阵)

(1).到第三行(最后一行)右移N(N=3)次,每次得到一个新的矩阵,每得到一个矩阵,求其最大值;

(2).到第二行移动三次,每移动一次,做一遍(1);

(3).到第一行移动三次,每移动一次,做一遍(2);

 

  优化:

  因为

1   0   2     和  0   1   2

4   3   5           3   4   5

7   6   8           6   7   8      .....是一样的

所以第一行可以不用右移动;若不能理解的话,把所有的写出来,看看;

递归关系简化为:

(1).到第三行(最后一行)右移N(N=3)次,每次得到一个新的矩阵,每得到一个矩阵,求其最大值;

(2).到第二行移动三次,每移动一次,做一遍(1);


注意,简化后,因为第一行没有排序,当输入N=1的时候,不能得出结果(具体看函数),所以当N==1时,结果单独输出;

if(N==1)//N==1直接输出结果,原因向下看
   printf("%d\n",A[0]);
          else         //否则进行排列递归,从第二行开始
          {
            pailie(A,N,1); //1表示从第二行开始移动(因为优化第一行不移动了),当N等于1时,看下面pailie
                               //实现,H==N,直接就返回了,所以N==1在上面单独输出
            free(A);
            printf("%d\n",comax_min);
          }

递归实现;

void pailie(int *A,int N,int H)
{

           if(H==N)     //当H==N,看上面例子,可以知道,前面已经到最后一行,所以返回上一个函数
             return;
            for(int j=0;j<N;j++)    //每一行移动N次
              {

                       pailie(A,N,H+1);   //递归到下一行

                      int t=A[N*(H+1)-1];     //记录这一行的最后一个元素
                       for(int i=N*(H+1)-1;i>N*H;i--)  //移动
                            A[i]=A[i-1];     
                              A[N*H]=t;

                        Colmax(A,N);   //求矩阵的最大值,同时里面会记录所有矩阵最大值的最小一个
              }
return ;
}


参考代码:

#include<stdio.h>
#include<malloc.h>
int comax_min;
void pailie(int *A,int N,int H);
void input(int *A,int N);
void Colmax(int *A,int N);
int main()
{
   int *A;
   int N;

   while(scanf("%d",&N)&&N!=-1)
   {
                 comax_min=100000;
                 A=(int *)malloc((N*N)*sizeof(int));
                 input(A,N*N);

                  if(N==1)
                     printf("%d\n",A[0]);
                   else
                       {
                           pailie(A,N,1);
                           free(A);
                           printf("%d\n",comax_min);
                       }

   }
return 0;
}

/*===================================================*/
void input(int *A,int N)
{
   for(int i=0;i<N;i++)
    scanf("%d",&A[i]);
}
/*===================================================*/
void pailie(int *A,int N,int H)
{

           if(H==N)
             return;
            for(int j=0;j<N;j++)
              {

                pailie(A,N,H+1);

                      int t=A[N*(H+1)-1];
                       for(int i=N*(H+1)-1;i>N*H;i--)
                            A[i]=A[i-1];
                              A[N*H]=t;

                        Colmax(A,N);

              }


return ;
}

/*===================================================*/
void Colmax(int *A,int N)   //求矩阵的最大值,并且求出所有矩阵中最大值最小的一个
{

   int max,sum=0;

   for(int j=0;j<N;j++)  //先求第一例的和
     sum+= A[j*N];
     max=sum;  //让最大值先等于第一列的和
     
   for(int i=1;i<N;i++)    //再求后面的列的和
   {   sum=0;
      for(int k=0;k<N;k++)
        {
          sum+=A[k*N+i];
        }
     if(max<sum)  //后面列的和更大,则更行max
     max=sum;

   }
  if(comax_min>max)   //记录所有矩阵最大值中最小的一个
    comax_min=max;
}


下面介绍全排列法以上方法就是它来的:(此方法仅供观赏,测试电脑性能)

同样把除了第一行以外的行,做全排列;

0   1   2    H=0  代表行:第一行 

3   4   5    H=1

6   7   8    H=2


把第二行做全排列,每得到一种排列,转向排列它的下一行,(同样每得到一种排列,排列它的下一行);若是最后一行,排列这一行,每一种排列求出这个矩阵的最大值。

//整个实现过程就是全排列里面,加上递归全排列,和求矩阵最大值
void pailie(int *A,int index,int length,int H,int N)
{

   int j=0;

   if(index==length)  //得到一种排列
    {
        if(H==N-1)   //看是不是最后一行
           Colmax(A,N);   //是最后一行,求矩阵最大值
          
           else
             pailie(A,(H+1)*N,(H+2)*N,H+1,N);  //不是最后一行,递归下一行

    }
    else
     for(j = index;j < length; j++)
        {
            swap(&A[j],&A[index]);
            pailie(A,index+1,length,H,N);
            swap(&A[j],&A[index]);
        }
return ;
}


参考代码:

#include<stdio.h>
#include<malloc.h>
int comax_min=0;
void pailie(int *A,int index,int length,int H,int N);
void swap(int *x,int *y);
void input(int *A,int N);
void Colmax(int *A,int N);
int main()
{
   int *A;
   int N;
   while(scanf("%d",&N)&&N!=-1)
   {
         comax_min=100000;
        A=(int *)malloc((N*N)*sizeof(int));
        if(N==1)
         {
         input(A,N*N);
         printf("%d\n",A[0]);
         }
         else
           {
               input(A,N*N);
               pailie(A,1*N,N+N,1,N);
               printf("%d\n",comax_min);
           }
   }
return 0;
}

/*===================================================*/
void input(int *A,int N)
{
   for(int i=0;i<N;i++)
    scanf("%d",&A[i]);
}
/*===================================================*/
void pailie(int *A,int index,int length,int H,int N)
{

   int j=0;

   if(index==length)
    {
        if(H==N-1)
           Colmax(A,N);

           else
             pailie(A,(H+1)*N,(H+2)*N,H+1,N);

    }
    else
     for(j = index;j < length; j++)
        {
            swap(&A[j],&A[index]);
            pailie(A,index+1,length,H,N);
            swap(&A[j],&A[index]);
        }
return ;
}

/*===================================================*/
void Colmax(int *A,int N)
{

   int max,sum=0;

   for(int j=0;j<N;j++)
     sum+= A[j*N];
     max=sum;
   for(int i=1;i<N;i++)
   {   sum=0;
      for(int k=0;k<N;k++)
        {
          sum+=A[k*N+i];
        }
     if(max<sum)
     max=sum;
   }

  if(comax_min>max)
    comax_min=max;
}
/*===================================================*/
void swap(int *x,int *y)
{
  int z=(*x);
  (*x)=(*y);
  (*y)=z;
return ;
}

别忘点赞哦-.-

 

0.0分

7 人评分

  评论区

好家伙  nb
2021-07-20 16:13:55
太溜了吧
2018-08-25 19:51:40
第二个容易超时
2018-04-11 22:59:48
  • «
  • 1
  • »