蓝桥杯算法入门_03 (枚举 - 回文数 - 最大子矩阵)

#include <iostream>
using namespace std;
#include<cstdlib>
#include<ctime>
/*枚举法
枚举范围循环 + 条件判断语句

*/

/*父亲年龄  - 27 == 儿子年龄    == 父亲年龄高低位互换    ,父亲年龄为两位数(10<= N <= 99)
枚举遍历 [10 - 99]  ,共有多少种情况
*/
void test_01() {
	int tot = 0; //记录解的个数
	for(int i = 10; i <= 99; i++) {
		if(i - (i % 10 * 10 + i / 10) == 27) {
			tot++;
		}
	}
	cout<< tot <<endl;
	return;
}


/*水仙花数
各个位上的数的三次幂之和 == 这个数本身
 求 [100,999] 之间的水仙花数
*/
void test_02() {
	for(int i = 100; i <= 999; i++) {
		int a,b,c;
		a = i % 10;  //个位
		b =  (i / 10) % 10   ;  //十位  == 取出十位和个位 / 10 (舍去个位) (i % 100)/ 10   ==    除基取余法  (i / 10) % 10
		c = i /100 ;  //取最高位    取次高位 i / 10 % 10  取个位 i % 10
		a = a*a*a;
		b = b*b*b;
		c = c*c*c;
		if(a + b + c == i) {
			cout<< i <<endl;
		}
	}

}

void test_03() { //找 n -- m 之间的质数
	int n,m;
	cin >> n >> m;
	if(n > m) {  //因下面的程序输入按照小到大寻找 ,确保 n为小的 ,否则直接终止循环
		swap(n,m);
	}
	for(int j = n; j <= m; j++) {
		if(j == 1) { // 要能正确列出所有情况  , 1不是质数 !!!
			continue;
		}
		bool is_prime = true;
		for(int i = 2; i < j; i++) {
			if(j % i == 0) {
				is_prime = false;
				/*
				cout<< j << "  NOT PRIME" <<endl;  //不是质数
				*/
				break;
			}
		}
		if(is_prime) {
			cout<< j << endl;   // << " is PRIME"
		}
	}
	return;
}

/* 随机生成了一个长度为10的只包含大写字母的字符串,让电脑自动枚举去猜,


// rand()%m+n: [n,n+m] 从m开始到m+n的m个数字范围内
// rand()%m: [0,m] 从0到m-1的m个数字范围内
// rand()%10 再除10 : 生成0到9的随机数,除10.0后,成为生成0到0.9的数字
*/

void test_04() {
	srand(time(NULL));
	char s[10];
	for(int i = 0; i < 10; i++) {
		s[i] = (char)(65 + rand() % 26);
		printf("%c",s[i]);  //print 不要加&  !!
	}
	printf("\n");
	for(int i = 0; i < 10; i++) {
		for(int j = 0; j < 26; j++) {
			if(s[i] == (char)(65 + j)) { //枚举先定前面,再下一位,降低时间复杂度
				cout<< (char)(65 + j);
				break;
			}
		}
	}
	return;
}

/*输入5 到 6 位数 之间满足条件的回文数    [10000,1000000) == [1e4,1e6)
条件 :找出 各个位置上的数值等于n的回文数  n ∈[10,100]
*/


int n_05;
int digit_05[6]; // 更新存回文数 输出
bool judge_05(int x) {
	int m = 0,sum = 0;
	while(x) {  //对x进行一次判断操作  x != 0
		digit_05[m++] = x % 10;   //存入每一位 从 个位 --> 最高位
		sum += x % 10; //sum为每位之和
		x /= 10;
	}
	if(sum != n_05) { // 相等
		return false;
	}
	for(int i = 0; i < m/2; i++) {
		if(digit_05[i] != digit_05[m - 1 - i]) { //首尾对比
			return false;
		}
	}
	return true;  //满足条件
}
void test_05() {
	bool f = false;
	cin >> n_05;
	for(int i = 1e4; i <= 1e6 ; i++) {    //1e4 -- 1e6
		if( judge_05(i) ) {
			cout<< i << endl;
			f = true;
		}
	}
	if(!f) { //不满足 f == false
		cout << -1 << endl;
	}
	return;
}

/*四叶玫瑰数
4位数 ,每位上的数的四次幂 等于它本身  即为四叶玫瑰数
[1000,9999]    [le4,le5)
*/

#include<cmath>   //不要用pow 可以算小数 复杂..  自己手写 更好
bool rose(int i) {  
	int a = i /1000 ,b = i /100 % 10, c = i / 10 % 10,d = i % 10;  //等效右移,取最后一位     !!!
	int ans = a*a*a*a + b*b*b*b + c*c*c*c +d*d*d*d;          
	if(ans == i) {
		return true;
	} else {
		return false;
	}
}

void test_06() {
	int n;
	cin >>n;
	if(n < 1e3 || n > 1e5) { //数字为紫色 !!  ,关键字为深黑色!! 括号为红色 !!  AC
		cout<< "error!";
	} else {

	}
	return;
}

/*每次过生日都吹蜡烛 ,通过共吹了几根蜡烛 ,判断从几岁开始过生日party 吹蜡烛,推出几岁 [1,200]
 依次枚举某岁到某岁之间会吹多少根蜡烛
*/

void test_07() {
	for(int i = 1; i <= 200; i++) {
		int can = 0,j = i;  //蜡烛数量can   , 年龄 j - 1

		while(can < 236 && j <= 200) {
			can += j;
			j++;
		}
		if(can == 236) { //从 i年 吹到 j - 1年
			cout<< i << " "<<j - 1<<endl;
		}
	}
	return;
}
/*迷信4不吉利
抽奖号码不要出现带有4的号码
号码为 n 到 m ,可以发行多少张    10000<= n,m <= 99999 [1e4,1e5)

输入
10000 99999  (不能1e4)

输出
52488
*/
bool judge(int x) { //有没有4 ,有返回true
	while(x) {
		if(x%10 == 4) {
			return true;
		}
		x /= 10;
	}
	return false;
}
void test_08() {
	int n,m,cnt = 0;
	cin >> n>> m;
	for(int i = n; i <= m; i++) {
		if(!judge(i)) { //不带4的发行 ,计数
			cnt++;
		}
	}
	cout<< cnt <<endl;
	return;
}

/*小学数学题  填入 1 ~ 13 不能重复 ,枚举所有情况  (较难第六届 #6题)
□+ □= □
□- □= □
□* □= □
□/ □= □

//优化时间!  如 7 + 8 = 15 > 13 直接舍弃  , 剪枝


*/

/* a^2 + b^2 + c^2 = n;  输入n ,求出所有解 a b c   (0 < a < b < c )

1000

输出
6 8 30
10 18 24
*/

void test_09() {
	int n;
	cin >> n;
	for(int a = 1; a*a<= n; a++) {   //循环枚举所有情况
		for(int b = a + 1; a*a + b*b <= n; b++) { //(0 < a < b < c )  -->  b = a + 1
			for(int c = b + 1; a*a + b*b + c*c <= n; c++) {  // (0 < a < b < c ) --> c = b + 1
				if(a*a + b*b + c*c == n) {
					cout<< a << " " << b << " "<< c << endl;
				}
			}
		}
	}
}
/*
n ×m 的矩阵 A ,输出最大子矩阵和

3 3
2 -4 1
-1 2 1
4 -2 2

输出
6
*/
int A_10[55][55];
void test_10() {
	int n,m ,ans;
	cin >> n >> m;
	ans = -1005;
	for(int i = 0; i < n; i++) {
		for(int j = 0; j < m; j++) {
			scanf("%d",&A_10[i][j]);
		}
	}
	for(int i = 0; i < n; i++) { //枚举边界 左边界k(从0开始遍历)  右边界l
		for(int j = i; j < n; j++) { //i j 上下边界 0开始 遍历
			for(int k = 0; k < m; k++) { // k 0-m 每行元素个数 == m(列数)
				for(int l = k; l < m; l++) {
					int tmp = 0;
					for(int p = i; p <= j; p++) { //p 从 i行 到 j行   子矩阵上下边界
						for(int q = k; q <= l; q++) { // q 从k列 到 l列  子矩阵左右边界
							tmp += A_10[p][q]; //求子矩阵元素和
						}
					}
					if(tmp > ans) {
						ans = tmp;  //更新找最大子矩阵元素和
					}
				}
			}
		}
	}
	cout<< ans <<endl; //输出
}

/*枚举算法练习
四平方和定理 (拉格朗日定理) :每个正整数都可以表示为至多4个整数的平方和。
如果把0包括进去,就正好可以表示为4个数的平方和。

如:
5 = 0^2 + 0^2 + 1^2 + 2^2 ;
7 = 1^2 + 1^2 + 1^2 + 2^2 ;

则对应任意正整数n ,都有:
n = a^2 + b^2 + c^2 + d^2 ;   (1 <= n <= 5000000) 5*1e6

输出
字典序最小的一组解 a b c d  (字典序 :如string,相同比较下一位 ,每位都相同 即相等  )


减少一层循环(d用 公式 sqrt( n- ( a*a + b*b + c*c ) )  )

减少多层 用方程组
*/
#include<cmath>
void test_11() {
	int N,d;
	scanf("%d",&N);
	for(int a = 0; a*a<= N; a++) {
		for(int b = a; a*a + b*b <= N; b++) { //b = a ,条件原则 :能遍历到所有情况 !!!!!
			for(int c = b; a*a + b*b + c*c <= N; c++) { //c = b = a 初始为0
				d = sqrt( N- ( a*a + b*b + c*c ) );
				if(a*a + b*b + c*c + d*d == N) {
					cout<<a << " "<< b << " "<< c << " "<< d << endl;  //找到就输出,a为最外层最慢遍历完,先找到就为最小字典序
					return;
				}

			}
		}
	}
	return;
}

/*
n宗不同颜色顺次相接而成,而每种颜色的装饰效果用一个整数表示  (连续数列 求子数列最大和)
选取装饰效果值最大的,小明也可以不用彩带,即值为0;
输入 n 颜色的数量 ,第二行 n个整数 依次为 a1,a2,...,an,(1 <= n <= 1000)

输入:
5
-1 2 -1 2 -1

输出:
3

*/

int a_12[1005];
void test_12() {
	int n,sum,ans;
	scanf("%d",&n);
	for(int i = 0; i < n; i++) {
		scanf("%d",&a_12[i]);
	}
	sum = 0;
	ans = 0;
	for(int i = 0; i < n; i++) {
		sum = 0;
		for(int j = i; j < n; j++) {
			sum += a_12[j];
			if(sum > ans) {
				ans = sum;
			}
		}
	}
	cout<<ans<<endl;
	return;
}

/* n根双节棍  (2<= n <= 100)    第i根 长度为 1 <= L <= 10000  ,两根双节棍长度差尽可能的小 (大 - 小  ,不要出现负数)
找到两根最合适的双节棍,输出最小的长度差

n 双节棍数量
n个整数 表每根双节棍长度    (找最小差值)

5
3 4 1 6 8

输出
1

*/

int L_13[105];
void test_13() {  //bug == 2
	int n,ans;
	scanf("%d",&n);
	for(int i = 0; i < n; i++) {
		scanf("%d",&L_13[i]);
	}
	ans = 10000;// 初始值 > 最大差值 10000 - 1   保证更新
	for(int i = 0; i < n; i++) {
		for(int j = i + 1 ; j < n; j++) {
			if(L_13[i] >= L_13[j]) {   //注意 大 - 小
				if(L_13[i] - L_13[j] < ans) {
					ans = L_13[i] - L_13[j];
				}
			} else {
				if(L_13[j] - L_13[i] < ans) {
					ans = L_13[j] - L_13[i];
				}
			}

		}
		cout<< ans <<endl;
		return;
	}
}
/*保留想法 
#include<set>
void test_set_13() { //排序后遍历找最小
	int n,elem,ans;
	set<int>s;
	scanf("%d",&n);
	for(int i = 0; i < n; i++) {
		scanf("%d",elem);
		s.insert(elem);
	}
	ans = 10000;
	//遍历set元素     ????

	for(set<int>::iterator it = s.begin(),p = s.begin() ;it != s.end() ;it++,p++) {  //bug

		if( *p - *it < ans) {
			ans = *p - *it;
		}
	}

	cout<<ans<<endl;
	return;
}

*/


int main() {
	test_13();
	return 0;
}












  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值