upc 个人训练赛第十场:组装玩具+河床(二分+最长不下降子序列)

本文主要是介绍upc 个人训练赛第十场:组装玩具+河床(二分+最长不下降子序列),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

问题 A: 金子数

题目描述
某地区有 n 条(编号依次为 1 到 n)互不交叉的道路,每条道路上都有 m 个数字,其中 能被 8 整除的数称为金子数,这个数字表示其重量。
如下表是 3 条道路,每条道路中有 5 个数的一种可能情况。
在这里插入图片描述
小华想在 n 条道路中走一条金子重量之和最大的道路,请编程帮他找出这条道路吧.

输入
输入共 n+1 行。
第 1 行两个整数 n 和 m,表示总共有 n 条道路,每条道路上有 m 个数。 接下来 n 行,每行 m 个正整数。

输出
输出共 1 行。 一个整数,表示金子重量之和最大的道路编号。
样例输入 Copy
3 5
13 24 17 8 23
1 2 3 4 5
16 2 16 4 8
样例输出 Copy
3
提示
输入的样例中,金子重量之和最大的道路编号为 3,具体情况见问题描述。

30%的测试点输入数据保证 1≤n≤10,1≤m≤100,路上的每个数都不超过 100。
100%的测试点输入数据保证 1≤n≤100,1≤m≤10000,路上的每个数都不超过 100000。 所有的测试点输入数据保证金子重量之和最大的道路只有一条,且肯定存在。

思路:
定义一个数组存储符合条件的数值即可

int m,n,sum,maxx;
int a[105][10005];
int b[105];
int main()
{scanf("%d%d",&n,&m);for(int i=0;i<n;i++)memset(a[i],0,sizeof(a[i]));memset(b,0,sizeof(b));for(int i=0;i<n;i++)for(itn j=0;j<m;j++)scanf("%d",&a[i][j]);for(int i=0;i<n;i++){for(int j=0;j<m;j++){if(a[i][j]%8 == 0)b[i] += a[i][j];}}maxx = b[0];for(int i=1;i<n;i++){if(maxx < b[i]){maxx = b[i];}}for(int i=0;i<n;i++){if(max == b[i])printf("%d",i+1);}return 0;
}

问题 B: 扑克牌游戏

题目描述
扑克牌有 13 种代表不同点数的牌(不考虑花色),如下图所示,从左到右依次为“A”, “2”,“3”,“4”,…… ,“10”,“J”,“Q”,“K”。

小华正在玩一个扑克牌的游戏,在这个游戏中,每种点数的牌都有一个分数(不一定 跟点数相同)。现在小华手上已经有 n 张扑克牌,他还可以挑选 m 张扑克牌,使得 n+m 张 扑克牌的总分数最大。我们假定每种点数的扑克牌有无穷多张。
请编程计算小华在游戏中可以最多获得多少分?

输入
输入共 3 行。
第 1 行 13 个整数,依次表示每种点数的牌所代表的分数。
第 2 行两个整数 n 和 m,表示小华已经有 n 张扑克牌,还可以挑选 m 张扑克牌。
第 3 行输入表示小华手上已经有的 n 张扑克牌的情况,输入的两张扑克牌信息之间没有 空格分隔。

输出
输出共1行。 输出一个整数,表示小华在游戏中可以获得的最大分数。注意:小华选牌的方案可能不唯一,但只要总分数最大即可,不需要输出选牌的方案。
样例输入 Copy
1 3 1 1 1 1 2 3 4 1 3 0 1
3 2
234
样例输出 Copy
13
提示
小华原来手上有 3 张牌,分别为“2”,“3”,“4”,对应的分数之和为 3+1+1=5,他可以 再挑选 2 张扑克牌,都是点数为“9”的扑克牌,这 2 张牌的分数之和为 4+4=8,所以小华的总得分为 13 分。

50%的测试点输入数据保证小华手上已经有的牌中不会出现“A”、“10”、“J”、“Q”、“K” 这 5 种点数的牌。
80%的测试点输入数据保证小华手上已经有的牌中不会出现“10”这种点数的牌。
100%的测试点输入数据保证 1≤n≤100,0≤m≤100,0≤每种点数的牌所代表的分数≤1000。

思路:
这个输入的牌之间没有空格,所以需要整体输入,一共有n张牌,每次循环找就可以了

string s;
int n,m,maxx,sum,ans;
int a[15],b[105];
int main()
{a[0] = 0;maxx = -1;for(int i=1;i<=13;i++){cin >> a[i];if(a[i] > maxx)//先找出最大值 maxx = a[i];}cin >> n >> m;cin >> s;for(int i=0;i<n;i++){if(s[i] >= '2' && s[i] <= '9')sum += a[s[i]-'0'];if(s[i] == 'A')	sum += a[1];if(s[i] == 'J') sum += a[11];if(s[i] == 'Q')	sum += a[12];if(s[i] == 'K')	sum += a[13];if(s[i] == '1' && s[i+1] == '0'){sum += a[10];n++;}}ans = sum+m*maxx;cout << ans << endl;return 0;
}

问题 C: 垃圾装袋

题目描述
某城市环卫部门需要对分布在城市中不同地点的 n 堆(编号为 1 到 n)垃圾进行装袋处 理。现在有 m 个(编号为 1 到 m)垃圾袋可以使用。

一个容量为 v 的垃圾袋能装入不超过容量为 v 的垃圾,一堆垃圾要求只能用一个垃圾 袋来装,一个垃圾袋也只能用来装一堆垃圾(即一个垃圾袋不能在两个地方装垃圾)。一个 垃圾袋的价格是由垃圾袋的容量来决定,容量为 v 的垃圾袋价格为 v。

请编程帮环卫部门计算要将 n 堆垃圾全部装袋,用掉的垃圾袋最少值多少钱?

输入
输入共 3 行。
第 1 行两个正整数 n 和 m,表示需要处理 n 堆垃圾,现在有 m 个垃圾袋。 第 2 行 n 个整数,依次表示每堆垃圾的容量。
第 3 行 m 个整数,依次表示每个垃圾袋的容量。

输出
输出共 1 行。 输出一个整数,如果能将所有的垃圾装入已有的袋子,则输出用掉的垃圾袋最少值多少钱?如果无法将所有的垃圾装入 m 个袋子,则输出“-1”。
样例输入 Copy
3 4
3 6 4
4 5 7 3
样例输出 Copy
14
提示
有3堆垃圾,4个袋子,第1堆容量为3的垃圾用第4个容量为3的袋子装,第2堆容量为6的垃圾用第3个容量为7的袋子装,第3堆容量为4的垃圾用第1个容量为4的袋子 装,所以用掉的垃圾袋最少值3+7+4=14。

30%的测试点输入数据保证1≤n,m≤1000
70%的测试点输入数据保证1≤n,m≤10000
100%的测试点输入数据保证1≤n,m≤50000,每个垃圾袋的容量和每处垃圾的容量 不超过10000。

思路:
for循环找比垃圾容量大的袋子,找到就更新答案,并且让这个袋子等于零结束本次循环,最后查找等于零的袋子,如果袋子数量与垃圾堆的数量不相等,就证明无法将所有的垃圾装完

int n,m,ans,cnt;
int a[maxn],b[maxn];
int main()
{cin >> n >> m;for(int i=1;i<=n;i++)    cin >> a[i];for(int j=1;j<=m;j++)    cin >> b[j];sort(b+1,b+1+m);for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(b[j] >= a[i]){ans += b[j];b[j] = 0;break;}}}for(int i=1;i<=m;i++)if(b[i] == 0)   cnt++;if(cnt != n)    printf("-1\n");else    cout << ans << endl;return 0;
}

问题 D: 组装玩具

题目描述
小华打算用 n 种(编号为 1 到 n)材料组装玩具。其中第 i 种材料的数量为 Xi 个。组装一个玩具需要第 i 种材料 Yi 个。小华另外有 m 个万能材料,每个万能材料可以作为 n 种材料中的任意一个材料使用。

请编程计算小华最多可以组装多少个玩具?

输入
输入共3行。
第1行两个整数n和m,分别表示小华有n种材料和m个万能材料。第2行n个正整数,其中第i个整数Xi表示小华第i种材料有Xi个。
第3行n个正整数,其中第i个整数Yi表示小华组装一个玩具需要第i种材料Yi个。

输出
输出共 1 行。
一个整数,表示小华最多可以组装多少个玩具。

样例输入 Copy
1 1
1
1
样例输出 Copy
2
提示
输入中小华只有1个编号为1的材料,另外还有1个万能材料。组装一个玩具需要编号为1的材料1个。所以可以用1个编号为1的材料和1个万能材料分别组装1个玩具,共可以组装2个玩具。
50%的测试点输入数据保证1≤n≤1000, 1≤m≤104,1≤Xi, Yi≤104。
100%的测试点输入数据保证1≤n≤100000, 1≤m≤109,1≤Xi, Yi≤109。

思路:
这个题呢,是听了dalao的想法之后做出来的,虽然没有单调性,但是组装玩具没有先后之分,而且数据范围又很大,所以完全可以直接二分去寻找这个答案

ll n,m;
struct node
{ll x,y,z;
}a[maxn];ll check(ll k,ll m)
{for(int i=1;i<=n;i++){if(a[i].z < k)//当前可以组装的玩具比check值小,需要万能材料 m -= a[i].y*k-a[i].x;if(m < 0)	return 0;//万能材料不够用,说明当前情况不符合 }return 1;
}int main()
{cin >> n >> m;for(int i=1;i<=n;i++)	cin >> a[i].x;for(int i=1;i<=n;i++)	cin >> a[i].y;for(int i=1;i<=n;i++)	a[i].z = a[i].x/a[i].y;ll l = 0,r = 10*1e9;while(l < r){ll mid = (l+r) >> 1;if(check(mid,m))	l = mid+1;//当前情况符合了,说明还可以组装更多的玩具,扩大范围else	r = mid;}printf("%lld\n",l-1);return 0;
}

问题 E: 河床

题目描述
小明是一个地理学家,经常要对一段河流进行测量分析。他从上游开始向下游方向等距离地选择了N个点测量水位深度。得到一组数据d1,d2,……,dn,回到实验室后数据分析员根据需要对数据进行分析,发掘隐藏在数据背后的规律。最近,小明发现某种水文现象与河床地势有关,于是他指示分析员要找出一段河流中最大高低起伏差不超过K(k<=100)的最长的一段。这看似一个复杂的问题,由于任务紧急,分析员求助于你,并告诉你小明的所有数据,数据都精确到个位。
输入
包含2行,第一行是整数N和k,分别表示测量点的个数和博士要求的最大水深差(也就是河床地势差)。第二行有N个整数,表示从上游开始一次得到的水位深度为di。
输出
只有一行,是正数M,表示最长一段起伏不超过K的河流长度,用测量点个数表示。
样例输入 Copy
6 2
5 3 2 2 4 5
样例输出 Copy
4

思路:
其实说白了就是一个寻找最长不下降子序列
每次寻找更新最大值即可

itn n,k,tmp,sum,minn,maxx;
int a[maxn];
int main()
{cin >> n >> k;for(itn i=0;i<n;i++)	cin >> a[i];sum = 1;for(itn i=0;i<n;i++){maxx = a[i];minn = a[i];tmp = 1;for(itn j=i+1;j<n;j++){if(a[j] > maxx)	maxx = a[j];if(a[j] < minn)	minn = a[j];if(maxx - minn > k)	break;//一旦这两个数据的差大于k,一定不是当前序列else{tmp++;if(tmp > sum)	sum = tmp;}}}cout << sum << endl;return 0;
}

问题 F: 最长链

题目描述
现给出一棵N个结点二叉树,问这棵二叉树中最长链的长度为多少,保证了1号结点为二叉树的根。
输入
第1行为包含了一个正整数N,为这棵二叉树的结点数,结点标号由1至N。
接下来N行,这N行中的第i行包含两个正整数l[i], r[i],表示了结点i的左儿子与右儿子编号。如果l[i]为0,表示结点i没有左儿子,同样地,如果r[i]为0则表示没有右儿子。
输出
包括1个正整数,为这棵二叉树的最长链长度。
样例输入 Copy
6
2 3
4 5
0 6
0 0
0 0
0 0
样例输出 Copy
4
提示
样例解释
4-2-1-3-6为这棵二叉树中的一条最长链。
对于100%的数据,有N≤100000,且保证了树的深度不超过32768。

思路:
两次dfs
第一次从任意一个点搜到最远点
再从这个最远点搜到另一个最远点

/**
从任意一点搜到最远点
再从这一点开始搜
搜到最远点
一定是最长链 
**/
int n,ans;
int l[maxn],r[maxn],d[maxn];
void dfs(int k)
{if(!l[k] && !r[k]){d[k] = 1;	return ;}if(l[k])	dfs(l[k]);if(r[k])	dfs(r[k]);ans = max(ans,d[l[k]]+d[r[k]]);d[k] = max(d[l[k]],d[r[k]])+1;
}int main()
{cin >> n;for(int i=1;i<=n;i++)cin >> l[i] >> r[i];dfs(1);cout << ans << endl;return 0;
}int a[10]; 
int main()
{srand(time(0));for(itn i=0;i<10;i++){a[i] = rand() % (40)+1;cout << a[i] << endl;}return 0;
}

这篇关于upc 个人训练赛第十场:组装玩具+河床(二分+最长不下降子序列)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/209431

相关文章

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

hdu2289(简单二分)

虽说是简单二分,但是我还是wa死了  题意:已知圆台的体积,求高度 首先要知道圆台体积怎么求:设上下底的半径分别为r1,r2,高为h,V = PI*(r1*r1+r1*r2+r2*r2)*h/3 然后以h进行二分 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#includ

poj3261(可重复k次的最长子串)

题意:可重复k次的最长子串 解题思路:求所有区间[x,x+k-1]中的最小值的最大值。求sa时间复杂度Nlog(N),求最值时间复杂度N*N,但实际复杂度很低。题目数据也比较水,不然估计过不了。 代码入下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

uva 10131 最长子序列

题意: 给大象的体重和智商,求体重按从大到小,智商从高到低的最长子序列,并输出路径。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vect

poj 2976 分数规划二分贪心(部分对总体的贡献度) poj 3111

poj 2976: 题意: 在n场考试中,每场考试共有b题,答对的题目有a题。 允许去掉k场考试,求能达到的最高正确率是多少。 解析: 假设已知准确率为x,则每场考试对于准确率的贡献值为: a - b * x,将贡献值大的排序排在前面舍弃掉后k个。 然后二分x就行了。 代码: #include <iostream>#include <cstdio>#incl

poj 3104 二分答案

题意: n件湿度为num的衣服,每秒钟自己可以蒸发掉1个湿度。 然而如果使用了暖炉,每秒可以烧掉k个湿度,但不计算蒸发了。 现在问这么多的衣服,怎么烧事件最短。 解析: 二分答案咯。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <c

poj 3258 二分最小值最大

题意: 有一些石头排成一条线,第一个和最后一个不能去掉。 其余的共可以去掉m块,要使去掉后石头间距的最小值最大。 解析: 二分石头,最小值最大。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <c

poj 2594 二分图最大独立集

题意: 求一张图的最大独立集,这题不同的地方在于,间接相邻的点也可以有一条边,所以用floyd来把间接相邻的边也连起来。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <sta

poj 3692 二分图最大独立集

题意: 幼儿园里,有G个女生和B个男生。 他们中间有女生和女生认识,男生男生认识,也有男生和女生认识的。 现在要选出一些人,使得这里面的人都认识,问最多能选多少人。 解析: 反过来建边,将不认识的男生和女生相连,然后求一个二分图的最大独立集就行了。 下图很直观: 点击打开链接 原图: 现图: 、 代码: #pragma comment(