贪心算法习题

 

 

#include<iostream>
#include<algorithm>
using namespace std;
struct Match
{
	int start;
	int end;
}M[1000005];
bool cmp(Match a, Match b)
{
	return a.end < b.end;
}
int main()
{
	int n, i, j,m;
	cin >> n>>m;
	for (i = 0; i < n; i++) cin >> M[i].start >> M[i].end;
	sort(M, M + n, cmp);
	int pos = M[0].end;
	int ans = 1;//第一个区间必须选 
	for (i = 1; i < n; i++)
	{
		if (pos <= M[i].start&& M[i].start <m && M[i].end<m)
		{
			pos = M[i].end;
			ans++;
		}
	}
	cout << ans;
	return 0;
}

#include<iostream>
#include<algorithm>
using namespace std;
struct thing
{
	int v;
	int c;
};
bool cmd(struct thing num1, struct thing num2)
{
	return num1.v > num2.v;
}
int main()
{
	int sum = 0;
	struct thing num[9];
	int n;
	cin >> n;
	if (n > 9)
	{
		cout << "输入数据不符合要求" << endl;
		return 0;
	}
	for (int i = 0; i < n; i++)
	{
		cin >> num[i].v >> num[i].c;
	}
	sort(num, num + n, cmd);
	sum = num[0].v - num[0].c;
	int all = num[0].v;
	for (int i = 1; i < n; i++)
	{
		all += num[i].v;
		sum = sum + num[i].v - num[i].c * (i + 1);
		if (sum < 0)
		{
			cout << all << endl;
			return 0;
		}

	}
	cout << all << endl;
	return 0;
}

 

 

这里没有采用冒泡排序,而是直接采用了C++的sort函数 

#include<iostream>
#include<algorithm>
#define num 1001
using namespace std;
int val[num];//价值
bool cmp(int x, int y) {
	return x > y;
}
int main()
{
	int N, M,sum=0;
	cin >> N >> M;
	for (int i = 1; i <= N; i++)
	{
		cin >> val[i];
	}
	sort(val, val + N,cmp);
	for (int j = 1; j <= M; j++)
	{
		val[j] = 0;
	}
	for (int z = 1; z <= N; z++)
	{
		sum += val[z];
	}
	cout << sum << endl;
	return 0;
}

洛谷P1614

最近有 nn 个不爽的事,每句话都有一个正整数刺痛值(心理承受力极差)。爱与愁大神想知道连续 mm 个刺痛值的和的最小值是多少,但是由于业务繁忙,爱与愁大神只好请你编个程序告诉他。

#include<iostream>
using namespace std;
int n, m, a[100001], mi = 100000, t = 0;
int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)cin >> a[i];
    for (int i = 1; i <= n - m + 1; i++)
    {
        for (int j = 1; j <= m; j++)t += a[i + j - 1];
        if (t < mi)mi = t;
        t = 0;
    }
    cout << mi << endl;
    return 0;
}

洛谷P1803

题目描述

现在各大 oj 上有 nn 个比赛,每个比赛的开始、结束的时间点是知道的。

yyy 认为,参加越多的比赛,noip 就能考的越好(假的)。

所以,他想知道他最多能参加几个比赛。

由于 yyy 是蒟蒻,如果要参加一个比赛必须善始善终,而且不能同时参加 22 个及以上的比赛。

输入格式

第一行是一个整数 nn ,接下来 nn 行每行是 22 个整数 a_{i},b_{i}ai​,bi​ ( a_{i}<b_{i}ai​<bi​ ),表示比赛开始、结束的时间。

输出格式

一个整数最多参加的比赛数目。

输入输出样例

输入 #1复制

3
0 2
2 4
1 3

输出 #1复制

2
#include<iostream>
#include<algorithm>
using namespace std;
struct Match
{
	int start;
	int end;
}M[1000005];
bool cmp(Match a, Match b)
{
	return a.end < b.end;
}
int main()
{
	int n, i, j;
	cin >> n ;
	for (i = 0; i < n; i++) cin >> M[i].start >> M[i].end;
	sort(M, M + n, cmp);
	int pos = M[0].end;
	int ans = 1;//第一个区间必须选 
	for (i = 1; i < n; i++)
	{
		if (pos <= M[i].start )
		{
			pos = M[i].end;
			ans++;
		}
	}
	cout << ans;
	return 0;
}

洛谷P1190

学校里有一个水房,水房里一共装有mm个龙头可供同学们打开水,每个龙头每秒钟的供水量相等,均为11。

现在有nn名同学准备接水,他们的初始接水顺序已经确定。将这些同学按接水顺序从 11到nn编号,ii号同学的接水量为 w_iwi​。接水开始时,11到mm 号同学各占一个水龙头,并同时打开水龙头接水。当其中某名同学jj完成其接水量要求w_jwj​后,下一名排队等候接水的同学 kk马上接替 jj 同学的位置开始接水。这个换人的过程是瞬间完成的,且没有任何水的浪费。即jj 同学第 xx 秒结束时完成接水,则kk 同学第 x+1x+1 秒立刻开始接水。若当前接水人数 nn’不足 mm,则只有 nn’个龙头供水,其它 m-nm−n’个龙头关闭。

现在给出 nn 名同学的接水量,按照上述接水规则,问所有同学都接完水需要多少秒。

输入格式

第 11 行22 个整数 nn 和 mm,用一个空格隔开,分别表示接水人数和龙头个数。

第 22 行 nn 个整数w_1,w_2,…,w_nw1​,w2​,…,wn​,每两个整数之间用一个空格隔开,w_iwi​表示ii号同学的接水量。

输出格式

11 个整数,表示接水所需的总时间。

输入输出样例

输入 #1复制

5 3 
4 4 1 2 1 

输出 #1复制

4

输入 #2复制

8 4 
23 71 87 32 70 93 80 76 

输出 #2复制

1
#include <iostream>
using namespace std;
int s[11000], ans;    // 根据t的终止条件来想下s的大小
int main()
{
	int n, m; cin >> n >> m;
	for (int i = 1; i <= n; i++) cin >> s[i];    //  输入每个学生的接水量
	int t = m + 1;   // t用来记录下个学生的编号 
	while (t <= n + m)
	{
		for (int i = 1; i <= m; i++)     //  枚举m个水龙头 
		{
			s[i]--;
			if (s[i] == 0)
			{
				s[i] = s[t];     //  如果这个学生的水接完了 模拟换下一个学生来这个水龙头
				t++;
			}
		}
		ans++;      //  以上是模拟的1秒钟的接水时间 所有ans加一 
	}
	cout << ans;
	return 0;
}

洛谷P7427

题目描述

ljcc 和他的学妹在玩游戏,这个游戏共有 nn 轮,在第 ii 轮获胜会获得 ii 分,没有平局。

现在给出 ljcc 和学妹的得分,求是否有一种方案符合当前得分。

输入格式

从标准输入读入数据。

输入一行输入两个数 a,ba,b 代表 ljcc 和学妹的得分。

输出格式

输出到标准输出。

若有解,在一行输出一组合法的解。第一个数代表游戏总共进行了 nn 轮,之后若干个数表示 ljcc 在哪些局获胜了,每两个数用单个空格隔开,行末不允许有空格。若没有合法解输出 No

输入输出样例

输入 #1复制

10 5

输出 #1复制

5 1 2 3 4

说明/提示

由于 SPJ 问题,禁止输出行末空格、回车

a,b\le 2^{31}-1,1\le n\le 10^5a,b≤231−1,1≤n≤105

#include<iostream>
#define ll long long
using namespace std;
ll a, b, n;//long long莫忘 
int main()
{
    cin >> a >> b;
    n = sqrt(2 * (a + b));//求n 
    if (n * (n + 1) != 2 * (a + b))//判断是否相等 
    {
        //无解 
        cout << "No";
        return 0;
    }
    //有解 
    cout << n;
    for (int i = n; a>0; i--)//从n开始向下枚举 
    {
        if (a >= i)
        {
            a -= i;//尽量减大的 
            cout << " " << i;//注意格式 
        }
    }
    return 0;
}

洛谷P1684 

题目描述

大家知道,黄药师不仅武功高超,而且酷爱音乐和诗歌。看到桃花岛来了个新客人,而且不是靠真武功进来的,就准备为难为难你。

他写了一首N行诗句的诗歌,美中不足的是这些诗句并不押韵,黄药师非常想遵循古诗的押韵。诗歌被分为若干段,每段都是四行诗。每一句诗都有一个韵脚,假如A和B表示两种不同的韵脚,每段四行诗的韵脚只可能是 “AABB”, “ABAB”, “ABBA” 和“AAAA”中的一种。

黄药师将诗句的韵脚都编了号,具有相同编号的句子代表有相同的韵脚。现在,黄药师想删掉一些句子,使得剩下的都是遵循押韵规则的四行诗,而且不允许改变诗句的顺序。

现在就问你:如何找出满足条件最长的诗歌?

输入格式

第1行为一个整数N(1<=N<=4000),代表黄药师写的诗歌的句子数。

第2行为N个整数,分别表示每一行诗的韵脚,这些数字都是不超过10^9的正数,每个数之间用1个空格隔开。

输出格式

一行一个整数k,为黄药师最多能够得到的四行诗个数。

输入输出样例

输入 #1复制

15
1 2 3 1 2 1 2 3 3 2 1 1 3 2 2

输出 #1复制

3

题解:

首先按顺序用map来记录当前每个韵脚出现次数

题目中要求四行诗满足“AABB”、“ABAB”、“ABBA”和“AAAA”中的一种,即有一种韵脚出现四次或两种韵脚各出现两次

故若前出现次数超过两次的韵脚数有两个或有一个韵脚出现次数出现次数为四次,答案就加一且清空记录的数

代码如下:

# include <map>
# include <cstdio>
using namespace std;
int n,x;
map <int,int> f;
int s;
int ans;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&x);
		f[x]++;
		if(f[x]==2) s++;
		if(s==2)
		{
			ans++;
			s=0;
			f.clear();
		}
		if(f[x]==4)
		{
			ans++;
			s=0;
			f.clear();
		}
	}
	printf("%d",ans);
	return 0;
}

 洛谷P1223

题目描述

有 nn 个人在一个水龙头前排队接水,假如每个人接水的时间为 T_iTi​,请编程找出这 nn 个人排队的一种顺序,使得 nn 个人的平均等待时间最小。

输入格式

第一行为一个整数 nn。

第二行 nn 个整数,第 ii 个整数 T_iTi​ 表示第 ii 个人的等待时间 T_iTi​。

输出格式

输出文件有两行,第一行为一种平均时间最短的排队顺序;第二行为这种排列方案下的平均等待时间(输出结果精确到小数点后两位)。

输入输出样例

输入 #1复制

10 
56 12 1 99 1000 234 33 55 99 812

输出 #1复制

3 2 7 8 1 4 9 6 10 5

这题其实看样例也能看出来排队顺序就是从小->大排

序,但是也许有很多人找不出这题的公式,费尽一番心

思想出来了一个简单程序(蒟蒻专用),如果人数

为n个,每个人的排队时间就是a[i]×(n-i),所以总时

间sum就是每个人时间总和;排队顺序就用一个数组存

一下,后在时间进行排序的同时进行交换。

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
struct a
{
	int b, number;
};
bool cmp(a x, a y)
{
	return x.b < y.b;
}
int main()
{
	a a[1000];
	int n;
	double sum = 0;
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i].b;
		a[i].number = i;//序号存起来
	}
	sort(a+1, a +1+ n,cmp);
	for (int i = 1; i <= n; i++)
	{
		cout << a[i].number << " ";
	}
	cout << endl;
	for (int i = 1; i <= n; i++)   //这个循环用来计算总时间 
	{
		sum += a[i].b  * (n - i);
	}
	printf("%.2f\n", sum/n);  // 保留小数后两位输出 
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值