【算法笔记】暴力的枚举与dfs深搜

1.暴力枚举:填数游戏

枚举以下竖式:

  AB

*   C

———

CCC

我们一直ABC这三个数字分别是0-9的数,数据范围较小,我们可以尝试使用枚举法来解决这道题目,三重循环别枚举即可。

来一段伪代码:

for (int a=1;a<=9;a++)
  for (int b=1;b<=9;b++)
     for (int c=1;c<=9;c++)
        if (((a*10)+b)*a==c*111)
            进行统计,累加等处理;
2.noip2014比例简化

不难看出,这道题目的数据范围很小,按照题目给定的条件进行枚举即可.

3.已知n*n得01矩阵,求最大的连续子矩阵使得矩内全部为1

思路:如果用枚举法搜索最少能够优化到O(n^3)的时间复杂度,即二重循环枚举左上角,然后用一重循环从左到右枚举全1的矩阵,接着求最大值即可

伪代码如下:

for(int u=1;u<=n;u++)//枚举上
{
  for (int j=1;j<=n;j++)c[j]=1;//初始化
  for (int d=u;d<=n;d++)//枚举下
  {
    for (int j=1;j<=n;j++) c[j]*=a[d][j];//c[i]=1表示这是一个全i段,否则表示这不是一个全i段;
    从左到右查找全i段;
    求最大值;
  }
}
4.noip2016魔法阵

不说,满分难度较大,四重循环+暴力枚举=65分.很不错了.

5.24点游戏.

大致思路:搜索任意两个数,并尝试四种符号,然后dfs+回溯即可.

6.及格

[问题描述]

小A这学期上了一门课,这门课分数的评定标准如下:

课程分数=xa\%+yb\%+z*(100-a-b)\%,其中x为平时作业成绩、y为期中考试成绩、z为期末考试成绩,x,y,z,a,b,100-a-b均是不大于100不小于0的整数,最终分数如果有小数部分则直接舍去。

现在小A知道了自己平时作业、期中考试的成绩以及比例系数a和b,他想知道为了达到及格(60分),自己期末至少要得到多少分,如果小A无论如何都无法及格,那么就输出"poor little A!"(不含引号)。

[输入格式]

第一行一个正整数T,表示数据组数。

接下来T行,每行四个非负整数x,y,a,b。

[输出格式]

输出T行,分别表示每组数据中,小A期末要得到多少分,或者"poor little A!"

思路:如果用数学方法做会有数学问题,及除数为0,显然容易出错,因此推荐用枚举法,枚举z,0-100枚举,输出最后符合条件的数即可.
#include<bits/stdc++.h>
using namespace std;
int main()
{
	//freopen("pass.in","r",stdin);
	//freopen("pass.out","w",stdout);
	int t,x,y,a,b;
	cin>>t;
	for(int i=1;i<=t;i++) 
	{
		cin>>x>>y>>a>>b;
		bool flag=false;
		for(int z=0;z<=100;++z)
		{
			if(x*a+y*b+z*(100-a-b)>=6000)
			{
				cout<<z<<endl;
				flag=true;
				break;
			}
		}
		if(!flag)
			cout<<"poor little A!"<<endl;
	}
}
7.数排列
[问题描述]

给定一个nn个数的序列aiai,其中每项均为0011

你的任务是统计符合以下性质的11nn排列(排列中第ii项记为pipi)的个数:

ai=0ai=0,则要求pipiii的因数,否则要求pipiii的倍数。

[输入格式]

第一行一个正整数TT,表示数据组数。

接下来TT组数据,每组数据第一行一个正整数nn表示序列长度,第二行nn个用空格分隔的整数aiai

[输出格式]

对于每组数据输出一行一个正整数表示答案

思路:这道题就是回溯+dfs,套模板,枚举每一个数字最后输出方案即可

#include<bits/stdc++.h>
using namespace std;
int a[20],now[20],ans,n;
void find(int x)
{
	if (x>n)
	{
		ans++;
		return;
	}//超出范围统计结果并退出
	if (a[x]==0)
    	for (int i=1;i<=n;i++)
	    	if (x%i==0&&now[i]==0) 
	    	{
	    		now[i]=1;
	    		find(x+1);
	    		now[i]=0;
			}
	if (a[x]==1)
	    for (int i=1;i<=n;i++)
	        if (i%x==0&&now[i]==0)
	        {
	        	now[i]=1;
	        	find(x+1);
	        	now[i]=0;
		}//根据ai进行分类讨论,然后按照dfs回溯的模板写一遍即可
}
int main()
{
	//freopen("permutation.in","r",stdin);
	//freopen("permutation.out","w",stdout);
	int t;
	cin>>t;
	for (int i=1;i<=t;i++)
	{
		ans=0;
		for (int j=1;j<=20;j++){a[j]=0;now[j]=0;}
		cin>>n;
		for (int j=1;j<=n;j++) cin>>a[j];
		find(1); 
		cout<<ans<<endl;
	}
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值