2024年春季学期《算法分析与设计》练习11

A:最少硬币

假设有4种硬币,它们的面值分别为1分、5分、10分和25分。
现在要找给顾客n分钱。
请问怎样找零钱才能使给顾客的硬币个数最少?
输出所需最少硬币的枚数。

输入

输入需要找给顾客的零钱n(单位:分)。

输出

输出所需最少硬币的枚数。 

样例输入

8

10

63 

样例输出

4

1

#include<iostream>
using namespace std;
typedef long long ll; 
const int N=1e3+5;
int n,s;
int a[4]={25,10,5,1};
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    while(cin>>n)
    {
        s=0;
        for(int i=0;i<4;i++)
        {
                s+=n/a[i];
                n%=a[i];
        }
        cout<<s<<'\n';
    }
    return 0;
}

B:X星纸币

X星最新版纸币的面额很奇怪,一共有1元、4元、9元、16元、25元、100元六种不同的面额。
已知每种面额纸币的数量不限,现在需要从中选取若干张纸币组成N元(N为正整数)。
请编写一个程序计算组成N元最少需要的纸币数量。

输入

单组输入。
每组1行,包含一个正整数N,N<=10^6。 

输出

输出组成N元最少需要的纸币数量。 

样例输入

12 

样例输出

#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll; 
const int N=1e6+5,INF=0x3f3f3f3f;
int n,s;
int a[6]={100,25,16,9,4,1};
int f[N];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    memset(f,INF,sizeof f);
	f[0]=0;
	for(int i=1;i<=N;i++)	
		for(int j=0;j<6;j++)
			if(i>=a[j]) f[i]=min(f[i],f[i-a[j]]+1);
	cin>>n;
	cout<<f[n]<<'\n';
    return 0;
}

C:图书排序 

某图书销售管理系统需要对图书(Book)进行排序,每一本图书包含书名(bookName)、销量(bookSales)、价格(bookPrice)等属性,要求先按照销量由大到小排序,对于销量相同的图书再按照价格由小到大排序。

 输入

每组输入包括两个部分,第一部分为书的数量n,
接下来n行则为n本书的信息。 按顺序输入书名(不超过20个字)、销量、价格。

 输出

输出排序后的信息,每个属性用空格隔开。 

样例输入

7

C++程序设计 120 25.00

软件工程 96 48.00

高等数学 80 32.50

算法分析与设计 96 54.00

离散数学 96 28.00

计算机网络 96 36.00

操作系统 115 45.00

样例输出

C++程序设计 120 25.00

操作系统 115 45.00

离散数学 96 28.00

计算机网络 96 36.00

软件工程 96 48.00

算法分析与设计 96 54.00

高等数学 80 32.50

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll; 
const int N=1e4+5,INF=0x3f3f3f3f;
struct ts
{
    string mz;
    int xl;
    double jg;
    bool operator<(const ts& W)const{
    	if(xl==W.xl) return jg<W.jg;
    	return xl>W.xl;
	}
}a[N];
int n;
int main()
{
    //ios::sync_with_stdio(0);
    //cin.tie(0);
    cin>>n;
    for(int i=0;i<n;i++)
        cin>>a[i].mz>>a[i].xl>>a[i].jg;
    sort(a,a+n);
    for(int i=0;i<n;i++)
    {
        cout<<a[i].mz<<' '<<a[i].xl<<' ';
        printf("%.2lf\n",a[i].jg);
    }
    return 0;
}

D:月饼

月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼。现给定所有种类月饼的库存量、总售价、以及市场的最大需求量,请你计算可以获得的最大收益是多少。
注意:销售时允许取出一部分库存。样例给出的情形是这样的:假如我们有3种月饼,其库存量分别为18、15、10万吨,总售价分别为75、72、45亿元。如果市场的最大需求量只有20万吨,那么我们最大收益策略应该是卖出全部15万吨第2种月饼、以及5万吨第3种月饼,获得 72 + 45/2 = 94.5(亿元)。

输入

每个输入包含1个测试用例。每个测试用例先给出一个不超过1000的正整数N表示月饼的种类数、以及不超过500(以万吨为单位)的正整数D表示市场最大需求量。随后一行给出N个正实数表示每种月饼的库存量(以万吨为单位);最后一行给出N个正实数表示每种月饼的总售价(以亿元为单位)。数字间以空格分隔。

输出

对每组测试用例,在一行中输出最大收益,以亿元为单位并精确到小数点后2位。(四舍五入) 

样例输入

3 20

18 15 10

75 72 45

样例输出

94.50 

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll; 
const int N=1e4+5,INF=0x3f3f3f3f;
struct bb
{
    double p,v;
    bool operator<(const bb& W)const{
    	return p/v>W.p/W.v;
	}
}c[1005];
int m;
double s,n;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>m>>n;
    for(int i=0;i<m;i++) cin>>c[i].v;
    for(int i=0;i<m;i++) cin>>c[i].p;
    sort(c,c+m);
    for(int i=0;i<m;i++)
        if(n>=c[i].v)
        {
            s+=c[i].p;
            n-=c[i].v;
        }
        else
        {
            s+=n*(c[i].p/c[i].v);
            n=0;
        }
    printf("%.2lf\n",s);
    return 0;
}

E: 汽车加油问题 

一辆汽车加满油后可以行驶n千米。旅途中有k个加油站。若要使沿途的加油次数最少,请设计一个有效的算法。

输入

第一行有2个正整数n和k,表示汽车加满油后可行驶nkm,且旅途中有k个加油站。接下来1行中,有k+1个整数,表示第k个加油站与第k-1个加油站之间的距离。第0个加油站表示出发地,汽车已加满油,且在第0个加油站满油不算加油,第k+1个加油站表示目的地。(请处理到文件尾)

输出

最少加油次数。如果无法到达目的地,则输出“No Solution”。 

样例输入

7 7

1 2 3 4 5 1 6 6

样例输出

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll; 
const int N=1e5+5,INF=0x3f3f3f3f;
int n,k,s,cnt;
int a[N];
bool flag;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    while(cin>>n>>k){
	    s=cnt=0;
	    k++;
	    flag=false;
	    for(int i=0;i<k;i++) cin>>a[i];
	    for(int i=0;i<k;i++)
	        if(s+a[i]>n){
	            if(a[i]>n){
	                cout<<"No Solution\n";
	                flag=true;
	                break;
	            }
	            s=a[i];
	            cnt++;
	        }else s+=a[i];
	   if(!flag) cout<<cnt<<'\n';
	}
    return 0;
}

F: 最大收益

小X是一位精明的投资人,他每次都能够做出正确的投资判断。现在有N个项目,每个项目的总投资额和总收益已知,并且每一个项目都允许小X投资一部分,当然也就只能拿到一部分收益。
现在小X决定拿出M万元钱来进行投资,请你帮他设计一个算法来计算最大收益和。

输入

对于每一个样例,第1行包含两个正整数,分别是M和N,其中M<=10^6,N<=100。
第2行一共有2*N个整数(不一定是正整数),奇数位置(即2*N-1位置)的数字表示第N个项目的总投资额(万元),偶数位置(即2*N位置)的数字表示第N个项目的总收益(万元),两个数字之间用空格隔开。 

输出

小X可以获得的最大收益和(万元,结果保留两位小数)。 

样例输入

100 4

50 10 20 10 40 10 50 20

样例输出

37.50 

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll; 
const int N=1e5+5,INF=0x3f3f3f3f;
int n;
double m,s;
struct bb
{
	double p,v;
	bool operator<(const bb& W)const{
		return p/v>W.p/W.v;
	}
}c[1005];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>m>>n;
	for(int i=0;i<n;i++) cin>>c[i].v>>c[i].p;
	sort(c,c+n);
	for(int i=0;i<n;i++)
		if(m>=c[i].v)
		{
			s+=c[i].p;
			m-=c[i].v;
		}
		else
		{
			s+=m*(c[i].p/c[i].v);
			m=0;
		}
	printf("%.2lf\n",s);
    return 0;
}

G: 组个最小数

给定数字0-9各若干个。你可以以任意顺序排列这些数字,但必须全部使用。目标是使得最后得到的数尽可能小(注意0不能做首位)。例如:给定两个0,两个1,三个5,一个8,我们得到的最小的数就是10015558。现给定数字,请编写程序输出能够组成的最小的数。

输入

每个输入包含1个测试用例。每个测试用例在一行中给出10个非负整数,顺序表示我们拥有数字0、数字1、……数字9的个数。整数间用一个空格分隔。10个数字的总个数不超过200,且至少拥有1个非0的数字。

输出

在一行中输出能够组成的最小的数。 

样例输入

2 2 0 0 0 3 0 0 1 0 

样例输出

10015558 

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll; 
const int N=1e5+5,INF=0x3f3f3f3f;
string s;
int n,a[10];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    for(int i=0;i<10;i++) cin>>a[i];
    for(int i=0;i<10;i++)
        for(int j=0;j<a[i];j++) s+=i+'0';
    n=0;
    sort(s.begin(),s.end());
    while(s[n]=='0') n++;
    cout<<s[n];
    s=s.substr(0,n)+s.substr(n+1);
    cout<<s<<'\n';
    return 0;
}

H: 最后一滴血

在ACM/ICPC这样的程序设计竞赛中,最早解出一道题称为抢到FB(First Blood,第一滴血)。现在ACM/ICPC世界总决赛甚至为每道题的FB设立了特别奖。也许我们还可以设一个LB(Last Blood,最后一滴血)奖,奖给最后一个解出某题的队伍。注意:你不能先提交程序,得到Yes之后等比赛快结束时把它再交一遍,因为一旦一只队伍解出了某题,它对该题的所有后续提交都会被忽略。所有有本事的话,应该是写完程序以后先不交,等到比赛快结束时才交。当然,这样做浪费了很多罚时并且还有WA的风险,所以LB奖才显得有趣。输入一场比赛中所有提交和对应的结果,输出每道题的LB奖得主。

输入

输入仅包含一组数据。第一行为题数n、队伍数t和提交数m(5<=n<=12, 10<=t<=100, 1<=m<=1000)。以下m行每行包含time(0~300之间的整数,单位:分钟), teamID(1~t), problem(A~L)和结果(Yes或者No)。提交按照时间从小到大排序,所以即使两个提交的time相同,也有先后顺序(可能只差几秒钟)。任意两个提交的顺序都不会绝对相同,因此LB奖要么空缺,要么有惟一的得主。

输出

对于每组数据,输出每道题目的LB奖得主的提交时间和teamID,格式见样例。 

样例输入

5 10 18

0 2 B No

1 2 B Yes

20 3 A Yes

35 8 E No

40 8 E No

45 7 E No

50 10 A Yes

100 4 A No

120 6 B Yes

160 2 E Yes

180 2 A Yes

210 3 B Yes

240 10 B No

250 10 B Yes

270 2 B Yes

295 8 E Yes

295 7 E Yes

299 10 D Yes

样例输出

A 180 2

B 250 10

C - -

D 299 10

E 295 7

#include<iostream>
#include<set>
using namespace std;
typedef long long ll; 
const int N=1e5+5,INF=0x3f3f3f3f;
int n,l,m;
int t,tid;
char c;
string s;
set<int> st[26];
int ma[26],mma[26];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    while(cin>>n>>l>>m){
        while(m--){
            cin>>t>>tid>>c>>s;
            if(s=="Yes"){
                if(!st[c-'A'].count(tid)) {
                    st[c-'A'].insert(tid);
                    if(ma[c-'A']<=t){
                        ma[c-'A']=t;
                        mma[c-'A']=tid;
                    }
                }
            }
        }
        for(int i=0;i<n;i++){
            c='A'+i;
            cout<<c<<' ';
            if(ma[i]) cout<<ma[i]<<' '<<mma[i]<<'\n';
            else cout<<"- -\n";
        }
        for(int i=0;i<26;i++){
            ma[i]=mma[i]=0;
            st[i].clear();
        }
    }
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值