程序竞赛SDAU 小节(第四周)

这一周是把贪心结束了,dp动态规划开了一点头,感觉老师讲dp就是比自己看的 好!然后这一周贪心的题目也结束了,自己也有好多没做出来的而且老师贪心课件里有好几个难题。

①06:Communication System

We have received an order from Pizoor Communications Inc. for a special communication system. The system consists of several devices. For each device, we are free to choose from several manufacturers. Same devices from two manufacturers differ in their maximum bandwidths and prices.
By overall bandwidth (B) we mean the minimum of the bandwidths of the chosen devices in the communication system and the total price § is the sum of the prices of all chosen devices. Our goal is to choose a manufacturer for each device to maximize B/P.
输入
The first line of the input file contains a single integer t (1 ≤ t ≤ 10), the number of test cases, followed by the input data for each test case. Each test case starts with a line containing a single integer n (1 ≤ n ≤ 100), the number of devices in the communication system, followed by n lines in the following format: the i-th line (1 ≤ i ≤ n) starts with mi (1 ≤ mi ≤ 100), the number of manufacturers for the i-th device, followed by mi pairs of positive integers in the same line, each indicating the bandwidth and the price of the device respectively, corresponding to a manufacturer.
输出
Your program should produce a single line for each test case containing a single number which is the maximum possible B/P for the test case. Round the numbers in the output to 3 digits after decimal point.
样例输入
1 3
3 100 25 150 35 80 25
2 120 80 155 40
2 100 100 120 110
样例输出
0.649
wr思路:这个题我刚开始没读明白 ,它的意思是选一个最小轴就行了。,我以为是把所有的轴都加一起然后除以money,然后结果根本不是小数。后来看了别人的博客才明白题意,感觉自己理解好差
AC思路:这个题首先枚举轴长,然后根据每次的轴长来找最小的money
这个轴是从输入里面找出最大之和最小值,然后呢从最小值开始 到最大值结束,挨着枚举。然后内部程序就是在每个小设备里面 去比较商家的 价钱
如果这个轴比我枚举的轴还要长并且 money >当前的价格 就把 当前价格赋给money这个小设备结束了之后 把它加到ans里去 再去下一个小设备…依次进行

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
int w[110][110], m[110][110], a[110];
int main()
{
	int t; cin >> t; int maxx = 0, minn = 1000000;
	while (t--)
	{
		double s = 0;
		int n; cin >> n;
		for (int i = 1; i <= n; i++)
		{
			cin >> a[i];
			for (int j = 1; j <= a[i]; j++)
			{
				cin >> w[i][j] >> m[i][j];
				maxx = max(maxx, w[i][j]);
				minn = min(minn, w[i][j]);
			}
		}
		double ans = 0;
		for (int i = minn; i <= maxx; i++)
		{
			double s = 0;
			for (int j = 1; j <= n; j++)
			{
				int  money = 10000000;
				for (int h = 1; h <= a[j]; h++)
					if (w[j][h] >= i && money > m[j][h])
						money = m[j][h];
					s += money;
			}
			if (1.0*i/s>ans) ans = 1.0 * i / s;
		}
		printf("%.3f\n", ans);
	}
}

②12:电池的寿命

小S新买了一个掌上游戏机,这个游戏机由两节5号电池供电。为了保证能够长时间玩游戏,他买了很多5号电池,这些电池的生产商不同,质量也有差异,因而使用寿命也有所不同,有的能使用5个小时,有的可能就只能使用3个小时。显然如果他只有两个电池一个能用5小时一个能用3小时,那么他只能玩3个小时的游戏,有一个电池剩下的电量无法使用,但是如果他有更多的电池,就可以更加充分地利用它们,比如他有三个电池分别能用3、3、5小时,他可以先使用两节能用3个小时的电池,使用半个小时后再把其中一个换成能使用5个小时的电池,两个半小时后再把剩下的一节电池换成刚才换下的电池(那个电池还能用2.5个小时),这样总共就可以使用5.5个小时,没有一点浪费。

现在已知电池的数量和电池能够使用的时间,请你找一种方案使得使用时间尽可能的长。

输入
输入包含多组数据。每组数据包括两行,第一行是一个整数N (2 ≤ N ≤ 1000),表示电池的数目,接下来一行是N个正整数表示电池能使用的时间。

输出
对每组数据输出一行,表示电池能使用的时间,保留到小数点后1位。

样例输入
2
3 5
3
3 3 5
样例输出
3.0
5.5
WR思路:这题很奇怪 ,当时在另一个平台做的时候 当时分析的就两种电池 3 5 两种,怎么做的呢,当时就是分析n=2的时候 t就等于最小号的电池的时间
n>2的时候时间就等于 t总/2 然后我拿这个思路来做题 wr了十几遍 问了下同学 才点醒我这个梦中人啊。
AC思路 :跟我的WR有点相似的地方
首先从输入的数据中找出最长时间的电池Tmax并且计算所有的电池总时间
如果S-Tmax<=Tmax 这个说明最大的这个电池不可能完全用完 只能用掉S-Tmax
如果 S-Tmax>Tmax 就输出我那个思路中的 s/2

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<string>
#include<cmath>
using namespace std;
int main()
{
	int n;
	while (cin >> n)
	{
		double s=0, maxx=0;
		for (int i = 0; i < n; i++)
		{
			double u;
			cin >> u; s += u;
			maxx = maxx > u ? maxx : u;
		}
		double n_1 = s - maxx;
		if (maxx >= n_1)
			printf("%.1f", n_1);
		else
			printf("%.1f", s / 2);
		cout << endl;
	}

}

③拼点游戏 田忌赛马

C和S两位同学一起玩拼点游戏。有一堆白色卡牌和一堆蓝色卡牌,每张卡牌上写了一个整数点数。C随机抽取n张白色卡牌,S随机抽取n张蓝色卡牌,他们进行n回合拼点,每次两人各出一张卡牌,点数大者获得三颗巧克力,小者获得一颗巧克力,如果点数相同,每人各得二颗巧克力,使用过的卡牌不得重复使用。已知C和S取到的卡牌点数,请编程计算S最多和最少能得到多少颗巧克力。
输入
输入包含多组测试数据。
每组测试数据的第一行是一个整数n(1<=n<=1000),接下来一行是n个整数,表示C抽到的白色卡牌的点数,下一行也是n个整数,表示S抽到的蓝色卡牌的点数。
输入的最后以一个0表示结束。
输出
对每组数据,输出一行,内容是两个整数用空格格开,分别表示S最多和最少可获得的巧克力数。
样例输入
3
92 83 71
95 87 74
2
20 20
20 20
2
20 19
22 18
0
样例输出
9 5
4 4
4 4
WR:这个题我跟老师上课讲的一个题混了,我以为这个俩题思路一样,结果错了好几遍 。
AC:这个思路就是 用田忌赛马的思想来的。先去比较快马,我如果赢了就进行下一局
else 我不一定赢 我得去想办法用慢马来输一局
如果我的慢马快 我肯定赢
else
(我的慢马不一定赢 同时我的慢马<你的快马,那我输了
但是 如果我的慢马等于你的快马,加两分)
感觉这个题吧感觉自己没掌握住

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
int c[1200], s[1200], uc[1200], us[1200]; int n;
int calu(int c[],int s[])
{
	int sum = 0;
	int s1 = 0, s2 = 0, e1 = n - 1, e2 = n - 1;
	while (s2<= e2)
	{
		if (s[e2] > c[e1])//如果我的最大值 比你的还大 ,那我就加3分
		{
			sum += 3;
			e2--; e1--;//两个终点前移;
		}
		else if (s[e2] < c[e1])//如果我的最大值比你的小
		{
			sum += 1; s2++; e1--;//我用最小值来跟你比较,我加一分;
		}
		else//如果我们俩的最大值相等,那就去    比较慢马
		{
			if (s[s2] > c[s1])//如果我的慢马比你的慢马快
			{
				sum += 3; s2++; s1++;//那我加3分,起点后移
			}
			else//如果我的慢马比你的慢马慢
			{
				if (s[s2] < c[e1])//同时我的慢马比你的快马小,我用最慢的马跟你的最快的马比较。
				{
					s2++; e1--; sum += 1;//我的起点后移,你的终点前移,我加1分
				}
				else  //我的慢马等于你的快马  那我加两分     
				{
					s2++; e1--; sum += 2;
				}
			}
		}
	}
	return sum;
}
int main()
{
	
	
	while (cin >> n && n)
	{
		int ans1 = 0, ans2 = 0;
		for (int i = 0; i < n; i++)
		{
			cin >> c[i]; uc[i] = 0;
		}
		for (int i = 0; i < n; i++)
		{
			cin >> s[i]; us[i] = 0;
		}
		sort(c, c + n); sort(s, s + n);
		cout<<calu(c, s)<<" "<<4*n-calu(s,c)<<endl;//第二个4*n代表着总分数一句总分为四分。
		
	}
}

④21:Integer Intervals

An integer interval [a,b], a < b, is a set of all consecutive integers beginning with a and ending with b.
Write a program that: finds the minimal number of elements in a set containing at least two different integers from each interval.
输入
The first line of the input contains the number of intervals n, 1 <= n <= 10000. Each of the following n lines contains two integers a, b separated by a single space, 0 <= a < b <= 10000. They are the beginning and the end of an interval.
输出
Output the minimal number of elements in a set containing at least two different integers from each interval.
样例输入
4
3 6
2 4
0 2
4 7
样例输出
4
WR:这个区间问题我思路想过 就是按照右区间排序,但是我没想到要去用什么判断 ,就是没想到怎么判断这个区间到底在不在我所制定的区间内部。
AC:排好序之后
我用两个数V1 V2 来当 这个判断标准 首先这个V1,V2 是
v2=第一个坐标右区间 V1=v2-1 这个 v1v2组合 正好包含第一个区间的两个
然后接着去判断 下一个
两种情况 第一:当下一次的左区间 >v2这说明这个区间没有符合条件的所以这个情况就得 新增两个元素。然后 在把v1v2按照第一个数那样赋值
第二 当下一次的左区间<=v2并且左区间>v1 因为v1v2正好是俩元素 你现在就一个 所以s++ 然后v1=v2 v2=右区间

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iomanip>
using namespace std;
struct zuobiao
{
	int z,y;//左右
}a[10001];
int cmp(zuobiao a, zuobiao b)
{
	return a.y < b.y;
}
int main()
{
	int n; int s = 2;
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		cin >> a[i].z >> a[i].y;
	}
	sort(a, a + n, cmp);
	int v1 = a[0].y - 1, v2 = a[0].y;
	for (int i =1; i < n; i++)
	{
		//当z<=v2,z>v1时,此时少一个
		if (a[i].z <=v2&&a[i].z>v1)//左坐标比V1大比 V2小
		{
			s++;
			v1 = v2; v2 = a[i].y;
		}
		else
		{
			if (a[i].z>v2)//左坐标>v2
			{
				s += 2;
				v2 = a[i].y; v1=v2-1;
		}
		}
	}
	cout << s << endl;
}

自我反思:这个贪心的题 08:Cell Phone Network 15:胡 17:Heritage 22:Elevator Stopping Plan 23:特殊密码锁 这几个题 没完成 我一定抽时间去csdn上找题解想办法去搞明白,自己确实 几个读题感觉好费劲 自己作业都没完成 我一定想办法去弥补!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值