贪心算法分析

1、硬币问题

题目:
有1元、5元、10元、100元、500元的硬币各C1、C5、C10、C50、C100、C500枚。现在要用这些硬币来值付A元,最少需要多少枚硬币?假设本题至少存在一种支付方案。

限制条件:
0<=C1,C5,C10,C50,C100,C500<=10^9
0<=A<=10^9

输入样例:
C1=3,C5=2,C10=1,C50=3,C100=0,C500=2,A=620
输出样例:
6(500元1枚,50元2枚,10元1枚,5元2枚,合计6枚)

该问题中,我们优先使用面值较大的硬币。

#include<iostream>

using namespace std;

const static int v[6] = { 1,5,10,50,100,500 };

int C[6];
int count[6];
int A;

void init(){
	for(int i=0;i<6;i++){
		cin>>C[i];
	}
	cin>>A;
}

void sove(){
	int ans=0;
	for(int i=5;i>=0;i--){
		int temp=min(A/v[i], C[i]); //第i种硬币最多可以使用A/v[i]个,C[i],表示第i种硬币的个数,说以取两者较小值
		A-=temp*v[i];
		count[i]=temp;
		ans+=temp;
	}
	cout<<ans<<"(";
	for(int i=5;i>=0;i--){
		cout<<v[i]<<"元"<<count[i]<<"枚,";
	}
	cout<<")";
}

int main(){
	init();
	sove();
	return 0;
}

1、区间问题

问题:区间调度问题
现在又n项工作,每项工作分别在Si时间开始,在ti时间结束。对于每项工作,你都可以选择参与与否。如果选择了参与,那么自始至终都必须全程参与。此外,参与工作的时间段不能重叠(即使是开始的瞬间和结束的瞬间也是不允许的)。
限制条件:
1<=N<=100000
1<=si<=ti<=10^9

输入样例:
n=5, s={1,2,4,6,8}, t={3,5,7,8,10}
输出样例:
3(选取工作1、3、5)

算法分析:在可选工作中,每次都选择结束时间最早的工作。

设计代码如下:

#include<iostream>
#include<algorithm>

using namespace std;

#define MAX_N 100000

//用于对工作排序
pair<int, int> itv[MAX_N];
int N, S[MAX_N], T[MAX_N];

void init(){
	cin>>N;
	for(int i=0;i<N;i++){
		cin>>S[i];
	}

	for(int i=0;i<N;i++){
		cin>>T[i];
	}
}

void sove(){
	//对pair排序,T放入first,S放入second
	for(int i=0; i<N; i++){
		itv[i].first=T[i];
		itv[i].second=S[i];
	}
	sort(itv, itv+N); //按t(工作结束时间)排序
	int ans=0,t=0;
	for(int i=0; i<N ; i++){
		if(t<itv[i].second){
			ans++;
			t=itv[i].first;
		}
	}
	cout<<ans<<endl;
}

int main(){
	init();
	sove();
	return 0;
}

3、字典最小问题

题目:Best Cow Line(POJ 3617)
给定长度为N的字符串S,要构造一个长度为N的字符串T。T是一个空串,随后反复进行下列任意操作。
从S头部删除一个字符,加到T的尾部
从S尾部删除一个字符,加到T的尾部
目标是要构造字典序尽可能小的字符串T。
限制条件:
1<=N<=2000
字符串S只包含大写英文字母

输入示例:
N=6;
S=“ACDBCB”
输出示例:
ABCBCD

操作过程示意图:
操作过程

分析:

  • 不断取S的开头和末尾中较小的一个字符放入到T的末尾
    • 但是这样做会出现一个问题,如果S开头和末尾相同,接下来一个也相同,再接下一个也相同,……. 。这样的化难道需要我们依次进行判断怕然比较大小吗?其实不需要这样做,我们可以利用字符串比大小的原理来设计算法。
  • 比较字符串S和S‘ 的大小
  • 将较小的字符串的首字母移入T

代码如下所示:

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

string s;

string sr;

string t = "";

int N;


void init(){
    cin>> N;
    cin>> s;
    sr = s.substr(0,s.length());
    reverse(sr.begin(),sr.end());
}

void solve(){
    while (t.length()< N)
    {
        if(s.length() == 0){
            break;
        }
        if(sr.length() == 0){
            break;
        }

        if(s<=sr){
            t.append(s.substr(0,1));
            s = s.substr(1);
        }else{
            t.append(sr.substr(0,1));
            sr = sr.substr(1);
        }
    }
    
}

int main(int argc, char const *argv[])
{
    
    init();
    solve();
    cout<<t<<endl;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值