c++ 贪心法

编程挑战中的贪心策略与反例分析

先看第1049题:

1049. 取款

题目描述

你是一个银行小职员,你的日常工作就是根据客户要求,从银行里为他们提取特定数额的纸币。已知客户需要提取n元,你需要用最少的纸币数量凑出n元,请问最少要几张?

注意你所在国家只有以下面值的纸币:1元,2元,3元,9元。

贪心思路

先取面额大的钞票,尽量多

代码

#include <bits/stdc++.h>
using namespace std;
const int N=4;
int money[N]={9,3,2,1};
int main(){
	freopen("withdraw.in","r",stdin);
	freopen("withdraw.out","w",stdout);
	int n,ans=0;
	cin>>n;
	for(int i=0;i<N;i++){
		ans+=n/money[i];
		n%=money[i];
	}
	cout<<ans<<endl;
	return 0;
}

简简单单的呢!

oh no   其实,这个贪心法有反例    只不过不容易发现     这种贪心法是错的

以面值为25 20 10 5 1为例:

发现错误

哈哈哈,这就是我说的“反例

所以:有时的面值不能贪心!!!

 再来看第436题

436. 高智商罪犯

题目描述

共n个罪犯排成一排,第i个人智商为xi,现在需要将他们依次分组押运,每一组只可以安排相邻的若干个罪犯。为防止高智商罪犯联合逃脱,必须保证每一组的智商总和不超过m,求最少要分几组?如果无法完成要求输出0

代码

#include <bits/stdc++.h>
using namespace std;
const int N=10000;
int n,a,w[N];
int main(){
	freopen("criminal.in","r",stdin);
	freopen("criminal.out","w",stdout);
	cin>>n>>a;
	for(int i=0;i<n;i++) cin>>w[i];
	for(int i=0;i<n;i++)
		if(w[i]>a) {
			cout<<0<<endl;
			return 0;
		}
	int ans=1,sum=0;
	for(int i=0;i<n;i++)
	{
		sum+=w[i];
		if(sum>a) {
			ans++;
			sum=w[i];
		}
	}
	cout<<ans<<endl;
	return 0;
}

1050. 防御塔

题目描述

敌人有n架轰炸机依次向你飞来,第i架飞机高度为h[i]。你需要用防御塔发出防空导弹炸毁敌机。

你的防御塔有一个优点:第一枚导弹可以打中任意高度。

但是,你的防御塔也有一个缺陷:之后每次导弹的高度要比上一枚导弹低。

为了击中所有敌机,请问最少要安排几个防御塔?

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1009;
int n,h[N],d[N];
int cnt=0;
int main(){
	freopen("towerdefense.in","r",stdin);
	freopen("towerdefense.out","w",stdout);
	cin>>n;
	for(int i=0;i<n;i++) cin>>h[i];
	int j;
	for(int i=0;i<n;i++){
		for(j=0;j<cnt;j++)
			if(d[j]>h[i]) break;
		d[j]=h[i];
		if(j==cnt) cnt++;
	}
	cout<<cnt<<endl;
	return 0;
}

下课!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值