当前位置:首页 > 题解目录 > 正文内容

文具订购(NOI online入门组)

亿万年的星光4年前 (2021-04-09)题解目录1503

【题目描述】

小明的班上共有n元班费,同学们准备使用班费集体购买3种物品。

  1. 圆规,每个7元。

  2. 笔,每支4元。

  3. 笔记本,每本3元。小明负责订购文具,设圆规、笔、笔记本的订购数量为a,b,c,他订购的原则依次如下:

1.n元钱必须正好用光,即7a+4b+3c=n;
2.在满足以上条件的情况下,成套的数量尽可能大,即a,b,c中的最小值尽可能大。
3.在满足以上条件的情况下,物品的总数尽可能大,即a+b+c尽可能大。请你帮助小明求出满足条件的最优方案。可以证明若存在方案,则最优方案唯一。

【输入描述】

从文件order.in中读入数据。仅一行一个整数n表示班费数量。

【输出描述】

输出到文件order.out中。若方案不存在则输出-1.否则输出一行三个用空格分隔的非负整数a,b,c表示答案。

【输入样例1】

1

【输出样例1】

-1

【输入样例2】

14

【输出样例2】

1 1 1

【输入样例3】

33

【输出样子3】

1 2 6

【样例3解释】

a=2,b=4,c=1 也是满足条件1,2的方案,但是对于条件3,该方案只买了7个物品,不如a=1,b=2,c=6的方案。

【数据范围】

对于测试点1~6:n<=14。对于测试点7~12:n是14的倍数。对于测试点13~18:n<=100。对于所有测试点:0<=n<=105

【限制】

时间1.0s 、空间限制256MB。


【题目分析】

  • 最简单的方法是暴力枚举,也可以使用DP




#include <iostream>
#include <algorithm>
using namespace std;

int n;

int main(void) {

	cin>>n;

	if(n == 0) { //特判
		cout<<"0 0 0"<<endl;
		return 0;
	}

	for(int p=n/14; p>=0; p--) { //枚举最小值,也就是a的个数
		for(int j=p; j<=n/4; j++) //枚举b
			for(int k=p; k<=n/3; k++) //枚举c
				if(p*7+j*4+k*3 == n) { //如果有解
					cout<<p<<" "<<j<<" "<<k<<endl;
					return 0;//输出,结束程序
				}
	}
	cout<<"-1"<<endl;//无解输出-1
	return 0;//完美AC~
}



#include <bits/stdc++.h>
using namespace std;
int main() {
	int n,ans=0;//ans用来记录套数
	cin>>n;
	if(n==0) { //若n=0,则直接输出答案;
		cout<<0<<" "<<0<<" "<<0;
		return 0;
	}
	if(n<6 && n!=4 && n!=3) { //若n无法分完,则直接输出答案;
		printf("-1");
		return 0;
	}
	ans=n/14;
	n%=14;//本代码的核心部分(个人觉得),求套数
	if(n<6 && n!=4 && n!=3 && n!=0)
		ans--,n+=14;//若在套数最多时n分不完,套数-1;
	if(n==0) { //若正好分完,直接输出三个套数
		cout<<ans<<" "<<ans<<" "<<ans<<endl;
		return 0;
	}
	//准备,最长if特判就要来了:
	if(n==3) {
		cout<<ans<<" "<<ans<<" "<<ans+1<<endl;
		return 0;
	}
	if(n==4) {
		cout<<ans<<" "<<ans+1<<" "<<ans<<endl;
		return 0;
	}
	if(n==6) {
		cout<<ans<<" "<<ans<<" "<<ans+2<<endl;
		return 0;
	}
	if(n==7) {
		cout<<ans<<" "<<ans+1<<" "<<ans+1<<endl;
		return 0;
	}
	if(n==8) {
		cout<<ans<<" "<<ans+2<<" "<<ans<<endl;
		return 0;
	}
	if(n==9) {
		cout<<ans<<" "<<ans<<" "<<ans+3<<endl;
		return 0;
	}
	if(n==10) {
		cout<<ans<<" "<<ans+1<<" "<<ans+2<<endl;
		return 0;
	}
	if(n==11) {
		cout<<ans<<" "<<ans+2<<" "<<ans+1<<endl;
		return 0;
	}
	if(n==12) {
		cout<<ans<<" "<<ans<<" "<<ans+4<<endl;
		return 0;
	}
	if(n==13) {
		cout<<ans<<" "<<ans+1<<" "<<ans+3<<endl;
		return 0;
	}
	if(n==15) {
		cout<<ans<<" "<<ans<<" "<<ans+5<<endl;
		return 0;
	}
	if(n==16) {
		cout<<ans<<" "<<ans+1<<" "<<ans+4<<endl;
		return 0;
	}
	if(n==19) {
		cout<<ans<<" "<<ans+1<<" "<<ans+5<<endl;
		return 0;
	}
	//是的,这样就没了(亲测,可以AC)
	return 0;
}


扫描二维码推送至手机访问。

版权声明:本文由青少年编程知识记录发布,如需转载请注明出处。

分享给朋友:

相关文章

剪刀石头布

【题目描述】石头剪子布,是一种猜拳游戏。起源于中国,然后传到日本、朝鲜等地,随着亚欧贸易的不断发展它传到了欧洲,到了近现代逐渐风靡世界。简单明了的规则,使得石头剪子布没有任何规则漏洞可钻,单次玩法比拼...

【题解】骨牌铺方格

【题解】骨牌铺方格

【题目描述】有1×n(n<=50)的一个长方形,用一个1×1、1×2和1×3的骨牌铺满方格,请问有多少种铺法?例如当n=3时为1×3的方格。此时用1×1、1×2和1×3的骨牌铺满方格,共有四种铺...

【题解】采摘花生2

【题目描述】Hello Kitty又一次来到花生地里摘花生,从左上角进入花生地,从右下角出去,只能向右或者向下,请问Hello Kitty应该沿着什么样的路线走,能够摘到的花生数量最多(假设花生地里没...

【题解】最大公约数(2019青岛市程序设计竞赛)

【问题描述】给定n,以及正整数序列a1,a2,…,an与b1,b2,…,bn。令:sa=a1*a2*…*ansb=b1*b2*…*bn求sa和sb的最大公约数gcd(sa,sb)。【输入】第一行n。第...

【题解】2020-T1 优秀的拆分

【题目描述】一般来说,一个正整数可以拆分成若干个正整数的和。例如,1=1,10=1+2+3+4等。对于正整数n的一种特定拆分,当且仅当在这种拆分下,n被分解为若干个不同的2的正整数次幂。注意,一个数x...

【题解】求车速问题

【题目描述】一辆以固定速度行驶的汽车,司机在上午10点看到里程表上的读数是一个对称数(即这个数从左向右读和从右向左读是完全一样的),为95859。两小时后里程表上出现了一个新的对称数。问该车的速度是多...