遍历矩阵的n^m种情况的解决办法

来源:互联网 发布:淘宝睡衣模特是谁 编辑:程序博客网 时间:2024/05/17 04:53

例如一个n*n的矩阵,矩阵中所给数据为正,且全部小于某一整数m,现在想要遍历矩阵第一列Matrix[0][i](0<=i<=n)的所有可能出现的情况:

那么Matrix[0][0]的取值范围为0~m;

Matrix[0][1]的取值范围为0~m;

...

Matrix[0][i](0<=i<=n)的取值范围也为0~m;

可知总共有n^m种情况,

但如何枚举这些情况呢?最简单的想法:用n个for循环实现,但这样有两个坏处,第一,由于不知道n的大小,所以实际上很难控制for循环的重数,第二,n重for循环,复杂度较大。

另一种想法,可以先算出所有的可能情况(一个总数NUM[n]),再通过for循环对所需情况进行赋值。

代码:

#include<iostream>#include<stdio.h>#include<cstring>#include<algorithm>#include<cmath>using namespace std;const int NUM[8]={0,1,4,16,64,256,1024,4096};//这里以m=4进行计算int flag[9][9];//矩阵大小n*n最大为9int main(){    int n;    while(scanf("%d",&n)!=EOF)    {        int count=0;        for(int i=0;i<NUM[n+1];i++)        {            memset(flag,0,sizeof(flag));            flag[1][1]=i%4;            printf("count=%d  flag[1][1]=%d   ",++count,flag[1][1]);            for(int j=2;j<=n;j++)            {                flag[1][j]=(i%NUM[j+1])/NUM[j];                printf("flag[1][%d]=%d   ",j,flag[1][j]);            }            printf("\n");        }    }return 0;}
一组输出数据:

3
count=1  flag[1][1]=0   flag[1][2]=0   flag[1][3]=0
count=2  flag[1][1]=1   flag[1][2]=0   flag[1][3]=0
count=3  flag[1][1]=2   flag[1][2]=0   flag[1][3]=0
count=4  flag[1][1]=3   flag[1][2]=0   flag[1][3]=0
count=5  flag[1][1]=0   flag[1][2]=1   flag[1][3]=0
count=6  flag[1][1]=1   flag[1][2]=1   flag[1][3]=0
count=7  flag[1][1]=2   flag[1][2]=1   flag[1][3]=0
count=8  flag[1][1]=3   flag[1][2]=1   flag[1][3]=0
count=9  flag[1][1]=0   flag[1][2]=2   flag[1][3]=0
count=10  flag[1][1]=1   flag[1][2]=2   flag[1][3]=0
count=11  flag[1][1]=2   flag[1][2]=2   flag[1][3]=0
count=12  flag[1][1]=3   flag[1][2]=2   flag[1][3]=0
count=13  flag[1][1]=0   flag[1][2]=3   flag[1][3]=0
count=14  flag[1][1]=1   flag[1][2]=3   flag[1][3]=0
count=15  flag[1][1]=2   flag[1][2]=3   flag[1][3]=0
count=16  flag[1][1]=3   flag[1][2]=3   flag[1][3]=0
count=17  flag[1][1]=0   flag[1][2]=0   flag[1][3]=1
count=18  flag[1][1]=1   flag[1][2]=0   flag[1][3]=1
count=19  flag[1][1]=2   flag[1][2]=0   flag[1][3]=1
count=20  flag[1][1]=3   flag[1][2]=0   flag[1][3]=1
count=21  flag[1][1]=0   flag[1][2]=1   flag[1][3]=1
count=22  flag[1][1]=1   flag[1][2]=1   flag[1][3]=1
count=23  flag[1][1]=2   flag[1][2]=1   flag[1][3]=1
count=24  flag[1][1]=3   flag[1][2]=1   flag[1][3]=1
count=25  flag[1][1]=0   flag[1][2]=2   flag[1][3]=1
count=26  flag[1][1]=1   flag[1][2]=2   flag[1][3]=1
count=27  flag[1][1]=2   flag[1][2]=2   flag[1][3]=1
count=28  flag[1][1]=3   flag[1][2]=2   flag[1][3]=1
count=29  flag[1][1]=0   flag[1][2]=3   flag[1][3]=1
count=30  flag[1][1]=1   flag[1][2]=3   flag[1][3]=1
count=31  flag[1][1]=2   flag[1][2]=3   flag[1][3]=1
count=32  flag[1][1]=3   flag[1][2]=3   flag[1][3]=1
count=33  flag[1][1]=0   flag[1][2]=0   flag[1][3]=2
count=34  flag[1][1]=1   flag[1][2]=0   flag[1][3]=2
count=35  flag[1][1]=2   flag[1][2]=0   flag[1][3]=2
count=36  flag[1][1]=3   flag[1][2]=0   flag[1][3]=2
count=37  flag[1][1]=0   flag[1][2]=1   flag[1][3]=2
count=38  flag[1][1]=1   flag[1][2]=1   flag[1][3]=2
count=39  flag[1][1]=2   flag[1][2]=1   flag[1][3]=2
count=40  flag[1][1]=3   flag[1][2]=1   flag[1][3]=2
count=41  flag[1][1]=0   flag[1][2]=2   flag[1][3]=2
count=42  flag[1][1]=1   flag[1][2]=2   flag[1][3]=2
count=43  flag[1][1]=2   flag[1][2]=2   flag[1][3]=2
count=44  flag[1][1]=3   flag[1][2]=2   flag[1][3]=2
count=45  flag[1][1]=0   flag[1][2]=3   flag[1][3]=2
count=46  flag[1][1]=1   flag[1][2]=3   flag[1][3]=2
count=47  flag[1][1]=2   flag[1][2]=3   flag[1][3]=2
count=48  flag[1][1]=3   flag[1][2]=3   flag[1][3]=2
count=49  flag[1][1]=0   flag[1][2]=0   flag[1][3]=3
count=50  flag[1][1]=1   flag[1][2]=0   flag[1][3]=3
count=51  flag[1][1]=2   flag[1][2]=0   flag[1][3]=3
count=52  flag[1][1]=3   flag[1][2]=0   flag[1][3]=3
count=53  flag[1][1]=0   flag[1][2]=1   flag[1][3]=3
count=54  flag[1][1]=1   flag[1][2]=1   flag[1][3]=3
count=55  flag[1][1]=2   flag[1][2]=1   flag[1][3]=3
count=56  flag[1][1]=3   flag[1][2]=1   flag[1][3]=3
count=57  flag[1][1]=0   flag[1][2]=2   flag[1][3]=3
count=58  flag[1][1]=1   flag[1][2]=2   flag[1][3]=3
count=59  flag[1][1]=2   flag[1][2]=2   flag[1][3]=3
count=60  flag[1][1]=3   flag[1][2]=2   flag[1][3]=3
count=61  flag[1][1]=0   flag[1][2]=3   flag[1][3]=3
count=62  flag[1][1]=1   flag[1][2]=3   flag[1][3]=3
count=63  flag[1][1]=2   flag[1][2]=3   flag[1][3]=3
count=64  flag[1][1]=3   flag[1][2]=3   flag[1][3]=3

输入为三是4^3=64,故共枚举从64种情况。

通过这种方法,可以很简单的枚举出n^m种情况的可能。

一个例题:

An Easy Puz

Wddpdh find an interesting mini-game in the BBS of WHU, called “An easy PUZ”. It’s a 6 * 6 chess board and each cell has a number in the range of 0 and 3(it can be 0, 1, 2 or 3). Each time you can choose a number A(i, j) in i-th row and j-th column, then the number A(i, j) and the numbers around it (A(i-1, j), A(i+1, j),A(i, j-1),A(i, j+1), sometimes there may just be 2 or 3 numbers.) will minus 1 (3 to 2, 2 to 1, 1 to 0, 0 to 3). You can do it finite times. The goal is to make all numbers become 0. Wddpdh now come up with an extended problem about it. He will give you a number N (3 <= N <= 6) indicate the size of the board. You should tell him the minimum steps to reach the goal.

Input

The input consists of multiple test cases. For each test case, it contains a positive integer N(3 <= n <= 6). N lines follow, each line contains N columns indicating the each number in the chess board.

Output

For each test case, output minimum steps to reach the goal. If you can’t reach the goal, output -1 instead.

Sample Input

3

1 1 0

1 0 1

0 1 1

3

2 3 1

2 2 1

0 1 0

Sample Output

2

3


这个题是暑假训练题目,难度还不错,值得一做。

思路:首先每个格子最多被选中3次并且选中顺序和最后答案无关,而且范围比较小,所以会考虑到枚举,但是直接枚举是4^36肯定无法接受。考虑第一行的状态确定以后,第二行的状态可以唯一确定,所以直接枚举第一行4^6就可以了。最后复杂度是O(4^6*36)。由于是只枚举第一行那么就跟枚举n^m种情况是一样的做法了。

AC代码:

#include<iostream>#include<stdio.h>#include<cstring>#include<algorithm>#include<cmath>#define MAX 7using namespace std;const int NUM[8]={0,1,4,16,64,256,1024,4096};int chess[MAX+1][MAX+1];int flag[MAX+1][MAX+1];int n,minNum;bool last;int main(){    //freopen("test.in","r",stdin);    //freopen("test.out","w",stdout);    while(scanf("%d",&n)!=EOF)    {        memset(chess,0,sizeof(chess));        minNum=1000000;        for(int k=1;k<=n;k++)            for(int m=1;m<=n;m++)                scanf("%d",&chess[k][m]);        int count=0;        for(int i=0;i<NUM[n+1];i++)//枚举第一行能改变的所有情况        {            memset(flag,0,sizeof(flag));            last=true;            flag[1][1]=i%4;            //printf("count=%d  flag[1][1]=%d   ",++count,flag[1][1]);            for(int j=2;j<=n;j++)            {                flag[1][j]=(i%NUM[j+1])/NUM[j];                //printf("flag[1][%d]=%d   ",j,flag[1][j]);            }            //printf("\n");            for(int k=2;k<=n+1;k++)            {                for(int m=1;m<=n;m++)                {                    int temp=chess[k-1][m]-flag[k-1][m-1]-flag[k-1][m]-flag[k-1][m+1]-flag[k-2][m];//这个式子很重要                    //printf("temp=%d\n",temp);                    while(temp<0)                        temp+=4;                    flag[k][m]=temp;                }            }            for(int j=1;j<n+1;j++)//考虑第n+1行,得到第n行是否满足条件                if(flag[n+1][j])                    last=false;            if(last)//满足条件,求出步数            {                int result=0;                for(int k=1;k<n+1;k++)                    for(int m=1;m<n+1;m++)                        result=result+flag[k][m];                if(result<minNum)                    minNum=result;//得到最小步数            }        }        if(minNum==1000000)//不可能的情况            printf("-1\n");        else            printf("%d\n",minNum);    }return 0;}


原创粉丝点击