遍历矩阵的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;}
- 遍历矩阵的n^m种情况的解决办法
- M*N的矩阵
- M * N 矩阵的骨牌覆盖问题
- 矩阵A(L*M)与矩阵B(M*N)的乘积
- 将M*N的矩阵旋转90度
- 将M*N的矩阵旋转90度
- 矩阵n*m找出最大值的行列号及值
- 通过递归遍历n位2进制数的所有情况
- 矩阵的m次方
- 求一个M*N的矩阵的最大子矩阵和。
- m的n次方
- python 把一个m*n的二维矩阵转换成一个m*n行,三列的列表
- 螺旋遍历n*m的方格,输出依次遍历的方格下标。。。。
- M*N矩阵旋转
- 求m*n矩阵中最大的子矩阵(元素和最大)
- 求N*M矩阵的转置矩阵(C语言)
- 求一个n*m阶矩阵中为1的矩阵最大面积
- 指数计算 m^n (可以扩展到矩阵的n次方)
- Django学习笔记之博客开发(二)
- 360浏览器安全学堂上线 提升用户安全指数
- git config配置文件
- c++中的list用法
- Singletons in Cocoa, are they evil?
- 遍历矩阵的n^m种情况的解决办法
- 黑马程序员----C#中的流程控制语句之循环语句
- iOS - 判断程序是否是第一次启动 & 进程延迟
- poj2886线段树+反素数
- 自定义调试信息的输出
- 按位运算符
- Ubuntu到12.04花屏位移解决办法
- git 实际使用记录
- 关于C-free工具中C调试出现DOS窗口闪过问题