【u012】数字游戏
Time Limit: 1 second
Memory Limit: 128 MB
【问题描述】
小W发明了一个游戏,他在黑板上写出了一行数字a1,a2,…an,然后给你m个回合的机会,每回合你可以从中选择一个数擦去它,接着剩下来的每个数字ai都要递减一个值bi如此重复m个回合,所有你擦去的数字之和就是你所得到的分数。 小W和他的好朋友小Y玩了这个游戏,可是他发现,对于每个给出的an和bn序列,小Y的得分总是比他高。小W很不服气,想让你帮他算算,对于每个an和bn序列,可以得到的最大得分是多少。这样他就知道有没有可能超过小Y的得分。
【输入格式】
输入文件game.in的第1行,一个整数n(1≤n≤200),表示数字的个数。 第2行,一个整数m(1≤m≤n),表示回合数。 接下来一行有n个不超过10000的正整数,a1,a2,…an,表示原始数字 最后一行有n个不超过500的正整数,b1,b2,…bn,表示每回合每个数字递减的值
【输出格式】
一个整数,表示最大可能的得分。结果输出到文件game.out。
Sample Input1
3
3
10 20 30
4 5 6
Sample Output1
47
【题解】
题意是这样的。无论你选什么数字。其他数字都会减去它相应的bi值,而不是说你选了数字k,然后其他数字减去bk。
这里我们要注意。可能我们擦掉的数字是一样的比如 1,2,3.
但是擦掉的顺序不同。结果也是不同的。
那应该如何选择顺序?
可以想象我们选择了a[i]和a[j],然后b[i] < b[j]。
那么我们要先选哪一个?
肯定是先选a[j]。因为我们可以避免a[j]在先选完a[i]之后减去较大的b[j];
可以写出这样ans=a[i]+a[j]-b[x].这个x就是后选的那一个的下标。
显然我们要让b[x]最小。那就先选a[j]后选a[i]。这样我们减去的就是较小的b[i]了。
知道了选择的顺序。接下来就要解决选哪些的问题了。
虽然优先选择b[x]较大的。
但是如果有这样的
a[] 10 100000
b[] 1000 2
然后m=1.也就是说我们只能选一个。那我们肯定要选择a[2]了。
又或者
a[] 2000 200 10000
b[] 100 99 90
m=2时。我们也不能单纯地选择a[1],a[2]。而应该选择a[1],a[3]。
综上。我们得出这样一个算法。
先把a[]按照b[]的大小降序排序。
然后,设f[i][j]表示前i个数,擦掉了j个数字得到的最大值。
f[i][j] = max{f[i-1][j],f[i-1][j-1]+a[i]-(j-1)*b[i]);
这里之所以要减去(j-1)*b[i]。是因为当前选的a[i]是第j个擦掉的数字。也就是说之前的j-1
回合。它都没有被擦掉,所以要扣掉(j-1)个b[i];
然后这个动态规划一定要在排完序之后做。
比如样例
3
3
10 20 30
4 5 6
如果我们不排序。
得到的f[1][1] = 6;
f[2][2] = f[1][1]+20-5*1 = 21;
f[3][3] = f[2][2] + 30-6*2 = 39;
而答案是47;
这里我们选择的也是1,2,3但是如果按照上面的方程。
我们是没有考虑到选择的顺序的。
也就是说到了a[3]这个决策的时候。
我们只会考虑以下3种顺序
a[1]->a[3];
a[1]->a[2]->a[3];
a[3];
因此。选择的顺序就显得尤为重要了。
这也是要排序的原因所在。
然后通过这个方程
f[i][j] = max{f[i-1][j],f[i-1][j-1]+a[i]-(j-1)*b[i]);
我们也可以看到。如果较小的b[i]放在比较靠后。减掉的会比较少。那相应的值也就更大了。
加深理解:
假如我们不将数组排序。
我们用dp选择出来的是一段序列c1,c2,c3,c4;
它是在不排序的基础上所能得到的最大值。
然后我们刚才讨论过。如果a[i],a[j]都选了,而b[i]<b[j]。
那我们一定是先选择a[j]的。所以我们可能要把这段序列排一下序。
把b[]大的放在前面。比如有序的序列可能变成c3,c2,c1,c4什么的。。
然后既然知道不管选什么都要按照b[]排序。那我们就在进行dp之前先排一下序。
这样才能保证其为最优的。(上面说的先dp后排序得出的不一定是最优值!我只是为了能让大家更好理解才说的);
【代码】
#include <cstdio>
int n, m, a[201], b[201], f[201][201] = { 0 };
int min(int a, int b) //返回a和b中的较小值
{
return a < b ? a : b;
}
int max(int a, int b) //返回a和b中的较大值
{
return a > b ? a : b;
}
int main()
{
scanf("%d", &n);
scanf("%d", &m);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= n; i++)
scanf("%d", &b[i]);
bool flag = false;
while (!flag) //按照b由大到小排序。冒泡排序
{
flag = true;
for (int i = 1;i <= n-1;i++)
if (b[i] < b[i + 1])
{
flag = false;
int t = a[i]; a[i] = a[i + 1]; a[i + 1] = t;//换的时候连同a要一起交换
t = b[i]; b[i] = b[i + 1]; b[i + 1] = t;
}
}
for (int i = 1; i <= n; i++)//进行dp
{
int maxj = min(i, m);//f[i][j]表示的是前i个数擦掉j个数的最大值
for (int j = 1; j <= maxj; j++) //j则不能超过i.但要到达m;
f[i][j] = max(f[i - 1][j], f[i - 1][j - 1] + a[i] - b[i] * (j - 1));
}
printf("%d\n", f[n][m]);//输出答案。
return 0;
}
【u012】数字游戏的更多相关文章
- C语言猜数字游戏
猜数字游戏,各式各样的实现方式,我这边提供一个实现方式,希望可以帮到新手. 老程序猿就不要看了,黑呵呵 源代码1 include stdio.h include stdlib.h include ti ...
- 不一样的猜数字游戏 — leetcode 375. Guess Number Higher or Lower II
好久没切 leetcode 的题了,静下心来切了道,这道题比较有意思,和大家分享下. 我把它叫做 "不一样的猜数字游戏",我们先来看看传统的猜数字游戏,Guess Number H ...
- java 猜数字游戏
作用:猜数字游戏.随机产生1个数字(1~10),大了.小了或者成功后给出提示. 语言:java 工具:eclipse 作者:潇洒鸿图 时间:2016.11.10 >>>>> ...
- 【原创Android游戏】--猜数字游戏Version 0.1
想当年高中时经常和小伙伴在纸上或者黑板上或者学习机上玩猜数字的游戏,在当年那个手机等娱乐设备在我们那还不是很普遍的时候是很好的一个消遣的游戏,去年的时候便写了一个Android版的猜数字游戏,只是当时 ...
- 【原创Android游戏】--猜数字游戏V1.1 --数据存储,Intent,SimpleAdapter的学习与应用
--------------------------------------------------------------- V0.1版本 上次做完第一个版本后,发现还有一些漏洞,并且还有一些可以添 ...
- NOIP2003pj数字游戏[环形DP]
题目描述 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易.游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分 ...
- Codevs 1229 数字游戏
1229 数字游戏 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver 题目描述 Description Lele 最近上课的时候都很无聊,所以他发明了 ...
- codevs 1229 数字游戏(可重集的全排列)
传送门 Description Lele 最近上课的时候都很无聊,所以他发明了一个数字游戏来打发时间. 这个游戏是这样的,首先,他拿出几张纸片,分别写上0到9之间的任意数字(可重复写某个数字),然后 ...
- XDU 1161 - 科协的数字游戏II
Problem 1161 - 科协的数字游戏II Time Limit: 1000MS Memory Limit: 65536KB Difficulty: Total Submit: 112 ...
- XDU 1160 - 科协的数字游戏I
Problem 1160 - 科协的数字游戏I Time Limit: 1000MS Memory Limit: 65536KB Difficulty: Total Submit: 184 ...
随机推荐
- Java学习笔记九
GUI:图形用户界面,Java不常用于创建桌面应用,所以用的比较少 一.概述: 二.Frame演示: 三.事件监听机制 import java.awt.Button; import java.awt. ...
- mahout中KMeans算法
本博文主要内容有 1.kmeans算法简介 2.kmeans执行过程 3.关于查看mahout中聚类结果的一些注意事项 4.kmeans算法图解 5.mahout的kmeans算法实现 ...
- html5 audio标签相关知识点总结
1.audio指JS原生对象,假如用jquery获取到audio标签后,需要dom[0]转为原生JS对象 if(audio.paused){ //如果音频暂停,就播放 audio.play(); }e ...
- Javascript和jquery事件--事件对象event
1. 事件对象event 对于event,js的解释是Event 对象代表事件的状态,比如事件在其中发生的元素.键盘按键的状态.鼠标的位置.鼠标按钮的状态.而jq的解释是事件处理(事件对象.目标元素 ...
- python中线程、进程和协程的区别
进程是资源分配的单位 线程是操作系统调度的单位 协程,又称微线程,纤程,协程的切换只是单纯的操作CPU的上下文,资源很小,效率高 进程切换需要的资源很最大,效率很低 一个程序至少有一个进程,一个进程至 ...
- BP神经网络公式推导及实现(MNIST)
BP神经网络的基础介绍见:http://blog.csdn.net/fengbingchun/article/details/50274471,这里主要以公式推导为主. BP神经网络又称为误差反向传播 ...
- 飞镖忍者 quick-cocos2d-x3.2
经典的入门小游戏.这里用quick-cocos2d-x3.2又一次写一遍,以便熟悉下quick 首先,创建project,假设不会自行百度啊. 1.编译效果例如以下: watermark/2/text ...
- python 命令行:help(),'more'不是内部或外部命令,也不是可运行的程序或批处理文件
Python下使用help(dict),显示'more'不是内部或外部命令,也不是可运行的程序或批处理文件,该如何处理? 环境变量设置的问题,进入 Path 的环境变量设置界面,将;%SystemRo ...
- iOS_05_iOS设备发展史
ios设备发展史 IPhone一代 * 2007年发布. * 支持电子邮件.移动电话.短信.网络浏览等. * 采取触摸键盘 * 3.5英寸,480 x 320像素. * 后置摄像投200万像素. IP ...
- [Nuxt] Update Vuex State with Mutations and MapMutations in Vue.js
You commit changes to state in Vuex using defined mutations. You can easily access these state mutat ...