暴力解法的小结

暴力暴力暴力 又简单到难

1,简单的暴力*:
何为暴力?:就是从小到大每次枚举了每个数字,如果遇到满足的解,就输出;这就叫做枚举暴力;

-eg.给定m,n,请问有多少个鸡和多少个兔,m是腿数,n是总数;输出鸡的数量和兔的数量;
input:m=36 ,n=11
output:4 7

#include <iostream>
using namespace std; 
int main()
{
    
    
	int m,n,i,j;//i表示鸡,j表示兔 
	cin>>m>>n;
	for(i=0;i<=n;++i)
	{
    
    
		for(j=0;j<=n;++j)
		{
    
    
			if((2*i+4*j==m)&&(i+j==n))//满足条件就输出,然后break掉
			{
    
    
				cout<<i<<" "<<j<<endl;
				break;
			}
		}
	}
}

优化的方法:该代码调用调用了2层循环,复杂度为n*n;
只要数据大了时间就变大了,所以我们可以简化代码,这个就可以化简代码时间和缩小规模:
**这题我们发现有一个i就可以用n-i表示兔子;

#include <iostream>
using namespace std; 
int main()
{
    
    
	int m,n,i,j;//i表示鸡,j表示兔 
	cin>>m>>n;
	for(i=0;i<=n;++i)
	{
    
    
		if(i*2+(n-i)*4==m) 
		{
    
    
			cout<<i<<' '<<n-i;
			break;
		}
	}
}

这个叫剪枝,就是当数据比较大的时候,就把一些已经超过了明显不可能的情况直接退出,简少代码运行量
大家一定听过蓝桥杯的“暴力搜索简枝”
2.最大乘积
输入n个元素组成序列s,找出一个乘积最大的序列,使得该序列最大
input:
3
2 4 -3
5
2 5 -1 2 -1
ouput:
8
20

#include <iostream>
using namespace std;
int main()
{
    
    
	int n,ans,max,b,a;
	while(cin>>n)
	{
    
    
	
		cin>>b;
		max=b;
		ans=b;
		for(int i=1;i<n;++i)
		{
    
    
			cin>>a;
			ans*=a;
			if(ans>max)
			{
    
    
				max=ans;
			}
		}
		cout<<max<<endl;
		
	}
}

这边可以看为每次输入一组数据就计算,每次一计算就直接比较大小,大于就更新。
3.分数拆分:
输入正整数k,找到所有的正整数x>=y
比如2
1/2=1/6+1/3;
1/2=1/4+1/4;
我们一开始会直接想一步步枚举,遇到可以的情况就输出
那么如何枚举呢,从什么到什么呢?似乎没有思路。
但是我们从表达式入手发现x《=y
那么1/x>=1/y即是1/k>=2/y;
那么y就<=2*k;
每次枚举就好了

注意分数和浮点数的加减乘除
1.因为浮点数在计算机里面是小数不精确的存储,所以不能用等于比较,那么要比较的话只能通分来得简单:
比如1/k=1/x+1/y;
通分变为xy=ky+k*x;


#include<iostream>
using namespace std;
 
int main()
{
    
    
	int k, x, y;
	while (cin >> k)
	{
    
    
		for (y = k + 1; y <= 2 * k; y++)
		{
    
    
			x = k*y / (y - k);//通过题目的等式很容易推出来的
			if (k*y % (y - k) == 0)//计算x是不是整数,是整数就判断出来输出
			{
    
    
				if (x >= y)
					cout << "1" << "/" << k << "=" << "1" << "/" << x << "+" << "1" << "/" << y << endl;
			}
		}
	}
	return 0;
}

这里有2个小技巧,
1.通过通分来计算可以避免分数的不确定比较;
2,这里x是整数,所以我们要判断x是不是整数;

如果一个正整数n至少在两种不同的进制下b1和b2下都是回文数(2<=b1,b2<=10),则称n是双基回文数(注意,回文数不能包含前导零)。输入正整数S<10^6,输出比S大的最小的双基回文数。
输入: 1600000
输出: 1632995
从头到尾巴
开始一个个枚举如果可以的话就输出
这里要写成2个函数一个是写成下一个进制的函数,一个是判断是否是回文。
回文和函数都设为数组不用数字的话就比较好比较;

/*
1.从下一个开始枚举;
2. 如果满足2个不同进制是回文就输出:
3.回文用数组来进行 
*/
#include <iostream>
using namespace std;
int a[30];
bool huiwen(int a[],int n)//从头到尾巴2边到中间进行比较,如果不对就返回false 不然就返回true;
{
    
    
	for(int i=0;i<=n/2;++i)
	{
    
    
		if(a[i]!=a[n-i]) return false;
	}
	return true;
}
bool converse(int n,int k) /*把十进制的n转化为k进制*/
{
    
    
    int flag=0,j=0,i;
    while(n)生成一个数组n进制的
    {
    
    
    	a[j++]=n%k;
    	n/=k;
	}
	if(huiwen(a,j-1))
	{
    
    
		flag=1;//如果是回文数,flag设为1;
	}
	if(flag)
	{
    
    
		return true;
	}
	else return false;
}
int main()
{
    
    
	int i,j,k,n,cnt;
    while(scanf("%d",&n)!=EOF)
    {
    
    
        for(j=n+1;;j++)
        {
    
    
            int p=0;
            for(i=2,cnt=0;i<=10;i++)
            {
    
    
                if(converse(j,i))
                   cnt++;  /*记录回文次数*/
                if(cnt>=2)  /*是双基回文数*/
                {
    
    
                    p=1;
                    break;
                }
            }
            if(p)
            {
    
    
                printf("%d\n",j);
                break;
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_51373056/article/details/109230574