枚举和模拟

一.枚举

(1)定义:一种基于已有知识来猜测答案的一种问题求解方法

(2)思想:
/*
不断猜测,从可能的答案中一一尝试,然后再判断题目的
条件是否成立
注意事项:
例:找出1-100中最大的质数
(1)确保答案正确性:
1.找对答案集合--->(1,100)
2.答案成立的条件--->最大的质数
(2)提高找答案的效率:
1.缩小答案枚举范围(50-100)
2.选择合适的枚举顺序--->逆序

*/

(3)例题:P1003 [NOIP 2011 提高组] 铺地毯 - 洛谷

基本题意:
/*
给定一个x,y坐标轴,平行于坐标轴水平铺设地毯
地毯之间可能会有所重叠,后面铺的地毯会覆盖前面
的地毯
问: 给定一个坐标值,求第几张地毯覆盖了这个点
*/

思路:
/*枚举每一个地毯,输入其基本坐标信息,
逆序输出每个地毯,判断给定的坐标值是否在
某个地毯范围内,满足条件则是第几个地毯,
如果没有找到就输出-1*/

解题代码:

//铺地毯 
#include
#include
using namespace std;
const int N=10010;
int n;
int a[N],b[N],g[N],k[N];
int flag=0; //记录是否有满足条件的地毯

int main()
{
	scanf("%d",&n);
	
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d%d%d",&a[i],&b[i],&g[i],&k[i]);
	}
	int x,y;
	scanf("%d%d",&x,&y);
	
	for(int i=n;i;i--)
	{
		if(x>=a[i]&&x<=a[i]+g[i]&&y>=b[i]&&y<=b[i]+k[i])  //需要满足的条件
		{
			printf("%d",i);
			flag=1;
			break;
		}
	}
	if(flag==0)
	{
		printf("%d",-1);
	}
 } 

二.模拟

模拟:
直接模拟题目中要求的操作
特点:码量大,操作多
有些操作题目不会自己给出,需要自己进行推导

模拟和枚举通常也被称为暴力方法

例题:

例题一:59. 螺旋矩阵 II - 力扣(LeetCode)
//基本题意:
/*
给定一个数字n,要去输出其n*n的顺时针螺旋矩阵
如下所示:
input: 3
output:
1 2 3
8 9 4
7 6 5
*/
//思路:
/*
使用模拟:
我们把上图的n*n型矩阵拆分为四个填充步骤,
只要添加的数字num<=n*n
我们就依次从第一行的从左往右,从上到下,从右往左,从下往上填充 
*/

解题代码:

//螺旋矩阵II 
#include
#include
using namespace std;

vectorint> > generateMatrix(int n) {
    vectorint> >a(n,vector<int>(n)); 
	int num=1;
	int t=0,b=n-1,l=0,r=n-1; 
    while(num<=n*n)
    {
    	 //从左往右填充
		 for(int i=l;i<=r;i++)
		 {
		 	 a[t][i]=num;
		 	 num++;
		  } 
		  t++;
		  //从上往下填充
		  for(int i=t;i<=b;i++)
		  {
		  	a[i][r]=num;
		  	num++;
		   } 
		  r--;
		  //从右往左填充
		  for(int i=r;i>=l;i--)
		  {
		  	a[b][i]=num;
		  	num++;
		   } 
		   b--;
		   //从下往上填充
		   for(int i=b;i>=t;i--)
		   {
		   	a[i][l]=num;
		   	num++;
			} 
			l++;
	}
	return a;
}

int main()
{
	int n;
	scanf("%d",&n);
	
	vectorint> > res=generateMatrix(n);
    for(int i=0;ifor(int j=0;jprintf("%d ",res[i][j]); 
		}
		putchar(10);
	}
	return 0;
	
}

理解贴图:枚举和模拟_第1张图片

例题二:59. 螺旋矩阵 II - 力扣(LeetCode)

/*
基本题意:
由题目可知新增两种石头剪刀布新手势,
并给出了胜负关系表,定义游戏一共进行 N 次猜拳。
每一次赢的人得 1 分,输的得 0 分;平局两人都得 0 分。
已知两个玩家的出拳都是有规律的,输入相关数据后,
问:进行N次猜拳后,两个玩家的分数各为多少
*/

//思路:
/*
1.我们可以在原表的基础上将其填充完整,并使用
二维数据记录各种出拳的得分情况
例如:f[i][j]=1 表示i对上j得一分
f[j][i]=0 表示j对上i不得分
2.接着我们模拟循环进行游戏,其中我们通过
取模来实现循环操作,(注意取模要从下标0开始)
3.最后统计分数,输出结果
*/

理解贴图:

枚举和模拟_第2张图片

解题代码:

//生活大爆炸版石头剪刀布 
#include
using namespace std;
int a[210],b[210]; //存储出拳周期 
//二维数组存储各种出拳的得分情况 
int f[5][5]={
	{0,0,1,1,0}, 
    {1,0,0,1,0},
    {0,1,0,0,1},
    {0,0,1,0,1},
    {1,1,0,0,0},
};
int main()
{
	int n,na,nb;
    scanf("%d%d%d",&n,&na,&nb);
    
    for(int i=0;i

你可能感兴趣的:(算法)