洛谷入门训练6:综合训练1

P1478 陶陶摘苹果(升级版)

这题一开始当成是模拟来做。后来发现其实是一个求最多方案的问题,因此有想过用动态规划。但是后来感觉太麻烦了,发现不如按照最少力气的一个个摘就可以了,后来才发现这就是贪心嘛。这里的sort()使用的是数组的特性,自己写了一个比较函数。

题目描述
又是一年秋季时,陶陶家的苹果树结了n个果子。陶陶又跑去摘苹果,这次她有一个a公分的椅子。当他手够不着时,他会站到椅子上再试试。

这次与NOIp2005普及组第一题不同的是:陶陶之前搬凳子,力气只剩下s了。当然,每次摘苹果时都要用一定的力气。陶陶想知道在s<0之前最多能摘到多少个苹果。

现在已知n个苹果到达地上的高度xi,椅子的高度a,陶陶手伸直的最大长度b,陶陶所剩的力气s,陶陶摘一个苹果需要的力气yi,求陶陶最多能摘到多少个苹果。

输入格式
第1行:两个数 苹果数n,力气s。

第2行:两个数 椅子的高度a,陶陶手伸直的最大长度b。

第3行~第3+n-1行:每行两个数 苹果高度xi,摘这个苹果需要的力气yi。

输出格式
只有一个整数,表示陶陶最多能摘到的苹果数。

输入输出样例
输入 #1复制
8 15
20 130
120 3
150 2
110 7
180 1
50 8
200 0
140 3
120 2
输出 #1复制
4

#include<iostream>
#include<algorithm>
using namespace std;
struct apple {
	int x;
	int y;
};

bool cmp(apple a1, apple a2) {
	return a1.y < a2.y;
}

int main() {
	int n, s;
	int a, b;
	cin >> n >> s;
	cin >> a >> b;
	auto apples = new apple[n];
	for (int i = 0; i < n; i++) {
		cin >> apples[i].x >> apples[i].y;
	}
	int count = 0;
	sort(apples, apples + n, cmp);
	for (int i = 0; i < n; i++) {
		if (s - apples[i].y >= 0 && (a + b >= apples[i].x)) {
			count++;
			s = s - apples[i].y;
		}
	}
	cout << count;
	return 0;
}

P1618 三连击

突然发现这种数字的问题,采用枚举+桶排真的是很强的方法。
题目描述
将1,2,…,9共9个数分成三组,分别组成三个三位数,且使这三个三位数的比例是A:B:C,试求出所有满足条件的三个三位数,若无解,输出“No!!!”。

//感谢黄小U饮品完善题意

输入格式
三个数,A B C。

输出格式
若干行,每行3个数字。按照每行第一个数字升序排列。

输入输出样例
输入 #1复制
1 2 3
输出 #1复制
192 384 576
219 438 657
273 546 819
327 654 981

#include<iostream>
using namespace std;

void GetDigit3(int num,int bucket[], int start,int end) {
	for (int i = end; i>=start ; i--) {
		bucket[i] = num % 10;
		num = num / 10;
	}
}

int main() {
	float a, b, c;
	cin >> a >> b >> c;
	c = c / a;
	b = b / a;
	int x, y, z;
	int xmax = 999 / c;
	int bucket[9];
	int sum = 0;
	int multi = 1;
	bool flag = 0;
	for (int x = 123; x <= xmax; x++) {
		sum = 0;
		multi = 1;
		y = x*b;
		z = x*c;
		GetDigit3(x, bucket, 0, 2);
		GetDigit3(y, bucket, 3, 5);
		GetDigit3(z, bucket, 6, 8);
		for (int i = 0; i < 9; i++) {
			sum += bucket[i];
			multi *= bucket[i];
		}
		if (sum == 45 && multi == 362880) {
			cout << x << " " << y << " " << z << endl;
			flag = 1;
		}
	}
	if (flag == 0)cout << "No!!!";

	return 0;
}
P1579 哥德巴赫猜想(升级版)

我用的是打表的方法,方案类问题打表真的太好用了。

题目背景
1742年6月7日哥德巴赫写信给当时的大数学家欧拉,正式提出了以下的猜想:任何一个大于9的奇数都可以表示成3个质数之和。质数是指除了1和本身之外没有其他约数的数,如2和11都是质数,而6不是质数,因为6除了约数1和6之外还有约数2和3。需要特别说明的是1不是质数。

这就是哥德巴赫猜想。欧拉在回信中说,他相信这个猜想是正确的,但他不能证明。

从此,这道数学难题引起了几乎所有数学家的注意。哥德巴赫猜想由此成为数学皇冠上一颗可望不可及的“明珠”。

题目描述
现在请你编一个程序验证哥德巴赫猜想。

先给出一个奇数n,要求输出3个质数,这3个质数之和等于输入的奇数。

输入格式
仅有一行,包含一个正奇数n,其中9<n<20000

输出格式
仅有一行,输出3个质数,这3个质数之和等于输入的奇数。相邻两个质数之间用一个空格隔开,最后一个质数后面没有空格。如果表示方法不唯一,请输出第一个质数最小的方案,如果第一个质数最小的方案不唯一,请输出第一个质数最小的同时,第二个质数最小的方案。

输入输出样例
输入 #1复制
2009
输出 #1复制
3 3 2003
#include<iostream>
#include<cstring>
#include<math.h>
using namespace std;
#define maxsize 20000
int Prime[maxsize+1];

bool IsPrime(int x) {
	bool flag = 1;
	for (int i = 2; i <=sqrt(x); i++) {
		if (x%i == 0) {
			flag = 0;
			break;
		}
	}
	return flag;
}

int main() {
	memset(Prime, 0, maxsize * sizeof(int));
	Prime[2] = 1;
	int n;
	cin >> n;
	for(int i=3;i<n;i++){
		if (IsPrime(i)) { 
			Prime[i] = 1; 
		}
	}//打表
	bool FlagFind = 0;
	for (int i = 2; i < n; i++) {
		for (int j = i; j < n; j++) {
			if (Prime[i] == 1 && Prime[j] == 1 && n - i - j >= 0 && Prime[n - i - j] == 1) {
				cout << i << " " << j << " " << n - i - j << endl;
				FlagFind = 1;
					break;
			}
		}
		if (FlagFind == 1)break;
	}

	return 0;
}
P2089 烤鸡

这道题目是真的有点秀了,提示要用枚举,然后真的枚举大法好,直接就枚举出来了。暴力枚举确实给我留下了很深的映像(毕竟每个数都是独立的,也没有写剪枝),直接最后暴力判断。

题目背景
猪猪hanke得到了一只鸡

题目描述
猪猪Hanke特别喜欢吃烤鸡(本是同畜牲,相煎何太急!)Hanke吃鸡很特别,为什么特别呢?因为他有10种配料(芥末、孜然等),每种配料可以放1—3克,任意烤鸡的美味程度为所有配料质量之和

现在,Hanke想要知道,如果给你一个美味程度,请输出这10种配料的所有搭配方案

输入格式
一行,n<=5000

输出格式
第一行,方案总数

第二行至结束,10个数,表示每种配料所放的质量

按字典序排列。

如果没有符合要求的方法,就只要在第一行输出一个“0”

输入输出样例
输入 #1复制
11
输出 #1复制
10
1 1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 2 1
1 1 1 1 1 1 1 2 1 1
1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 2 1 1 1 1
1 1 1 1 2 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1
1 1 2 1 1 1 1 1 1 1
1 2 1 1 1 1 1 1 1 1
2 1 1 1 1 1 1 1 1 1

#include<iostream>
using namespace std;
int main() {
	int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
	int count, target;
	cin >> target;
	count = 0;
	for (a1 = 1; a1 <= 3; a1++)
		for (a2 = 1; a2 <= 3; a2++)
			for (a3 = 1; a3 <= 3; a3++)
				for (a4 = 1; a4 <= 3; a4++)
					for (a5 = 1; a5 <= 3; a5++)
						for (a6 = 1; a6 <= 3; a6++)
							for (a7 = 1; a7 <= 3; a7++)
								for (a8 = 1; a8 <= 3; a8++)
									for (a9 = 1; a9 <= 3; a9++)
										for (a10 = 1; a10 <= 3; a10++) {
											if (a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 == target)count++;
										}
	cout << count << endl;

	for (a1 = 1; a1 <= 3; a1++)
		for (a2 = 1; a2 <= 3; a2++)
			for (a3 = 1; a3 <= 3; a3++)
				for (a4 = 1; a4 <= 3; a4++)
					for (a5 = 1; a5 <= 3; a5++)
						for (a6 = 1; a6 <= 3; a6++)
							for (a7 = 1; a7 <= 3; a7++)
								for (a8 = 1; a8 <= 3; a8++)
									for (a9 = 1; a9 <= 3; a9++)
										for (a10 = 1; a10 <= 3; a10++) {
											if (a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 == target) {
												cout << a1 << " ";
												cout << a2 << " ";
												cout << a3 << " ";
												cout << a4 << " ";
												cout << a5 << " ";
												cout << a6 << " ";
												cout << a7 << " ";
												cout << a8 << " ";
												cout << a9 << " ";
												cout << a10 << "\n";
											}
										}


	return 0;
}
P2089 烤鸡 递归体会

后来看了别人的递归算法,虽然是同一个意思,但是感觉也挺有趣的,记录下来,也能帮助我更好的体会递归。 看完之后我更加觉得,递归的本质其实和递推是有点像的,在外部变量的作用下,在递归函数中,变量按照递归的规则在往一个方向发展,对于有分支的情况采用循环和遍历来写,比如下面的for(int i=1;i<=3;i++)这里的本质其实就是处理一种并列的分支结构。

//来个短短的递归~~(估计没人看...)
#include<iostream>
using namespace std;
int n,kind=0,m1[10000][10],m2[10];
void peiliao(int total,int a){
    if (a==10){
        if (total==n) {
            for (int j=0;j<10;j++) m1[kind][j]=m2[j];//符合要求存起来~~ 
            kind++;
        }
    }
    else if (total>=n) ;//小小优化一下 
    else
      for (int i=1;i<=3;i++){
          m2[a]=i;
          peiliao(total+i,a+1);//其实这和十连for没什么区别。。。 
      }
}
int main(){
    cin>>n;
    peiliao(0,0);
    cout<<kind<<endl;
    for (int j=0;j<kind;j++){
      for (int i=0;i<10;i++) cout<<m1[j][i]<<" "; //大家一定要记得打空格... 
     cout<<endl; 
    }
    return 0;
}
#include<iostream>
using namespace std;
int n;
int kind = 0;
int method[10];
int totalmethod[60000][10];//3^10=59000

void f(int total, int Hkind) {
	if (Hkind == 10) {
		if (total == n) {
			for (int i = 0; i < 10; i++) {
				totalmethod[kind][i] = method[i];
			}
			kind++;
		}
	}
	else if (Hkind < 10&&total<n) {
		for (int i = 1; i <= 3; i++) {
			method[Hkind] = i;
			f(total + i, Hkind + 1);
		}
	}
}

int main() {
	cin >> n;
	f(0, 0);
	cout << kind + 1<<endl;
	for (int i = 0; i < kind; i++) {
		for (int j = 0; j < 10; j++) {
			cout << totalmethod[i][j] << " ";
		}
		cout << endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值