tyvj1048 田忌赛马
描述
输入格式
第二行有N个整数表示田忌的马的速度。
第三行的N个整数为齐王的马的速度。
输出格式
测试样例1
输入
3
92 83 71
95 87 74
输出
200
这个问题很显然可以转化成一个二分图最佳匹配的问题。把田忌的马放左边,把齐王的马放右边。田忌的马A和齐王的B之间,如果田忌的马胜,则连一条权为200的边;如果平局,则连一条权为0的边;如果输,则连一条权为-200的边。
然而我们知道,二分图的最佳匹配算法的复杂度很高,无法满足N=2000的要求。
我们不妨用贪心思想来分析一下问题。因为田忌掌握有比赛的“主动权”,他总是根据齐王所出的马来分配自己的马,所以这里不妨认为齐王的出马顺序是按马的速度从高到低出的。由这样的假设,我们归纳出如下贪心策略:
1、如果田忌剩下的马中最强的马都赢不了齐王剩下的最强的马,那么应该用最差的一匹马去输给齐王最强的马。
2、如果田忌剩下的马中最强的马可以赢齐王剩下的最强的马,那就用这匹马去赢齐王剩下的最强的马。
3、如果田忌剩下的马中最强的马和齐王剩下的最强的马打平的话,可以选择打平或者用最差的马输掉比赛。
第一个贪心策略的证明:
此时田忌的所有马都赢不了齐王的马,所以无论用最慢马去输还是用最快的马去输都同样是输,而处于贪心的思想,我们应该保留相比之下更强的马,因此用最慢的马去输一定不会比用别的马去输来得劣,所以这是最优策略。
证毕。
第二个贪心策略的证明:
假设现在齐王剩下的最强的马是A,田忌剩下的最强的马是B,如果存在一种更优的比赛策略,让B的对手不是A,而使得田忌赢更多的钱的话,那么设此时A的对手是b,B的对手是a:
若b>A,则有B>a,b>A。这个结果和B>A,b>a是相同的。
若a<b≤A,则有B>a,b≤A。这个结果不如B>A,b>a来得优秀。
若b≤a≤A,则有B>a,b≤A。这个结果和B>A,b≤a是相同的。
由此可知,交换各自对手后,一定不会使得结果变劣,那么假设是不成立的。
证毕。
第三个贪心策略的证明:
因为田忌最快的马也只是和齐王的马打平,那么田忌只能选择平或输,选择平的话,当然只能用最快的马去平了;选择输的话当时是用最慢的马去输来得值得,这和第一个贪心策略的思路是一样的。
证毕。
我们发现,第三个贪心策略出现了一个分支:打平或输掉。如果穷举所有的情况,算法的复杂度将比求二分图最佳匹配还要高;如果一概而论的选择让最强的马去打平比赛或者是让最差的马去输掉比赛,则存在反例:
光是打平的话,如果齐王马的速度分别是1 2 3,田忌马的速度也是1 2 3,每次选择打平的话,田忌一分钱也得不到,而如果选择先用速度为1的马输给速度为3的马的话,可以赢得200两黄金。
光是输掉的话,如果齐王马的速度分别是1 3,田忌马的速度分别是2 3,田忌一胜一负,仍然一分钱也拿不到。而如果先用速度为3的马去打平的话,可以赢得200两黄金。
虽然因为第三个贪心出现了分支,我们不能直接的按照这种方法来设计出一个完全贪心的方法,但是通过上述的三种贪心策略,我们可以发现,如果齐王的马是按速度排序之后,从高到低被派出的话,田忌一定是将他马按速度排序之后,从两头取马去和齐王的马比赛。有了这个信息之后,动态规划的模型也就出来了!
设f[i,j]表示齐王按从强到弱的顺序出马和田忌进行了i场比赛之后,从“头”取了j匹较强的马,从“尾”取了i-j匹较弱的马,所能够得到的最大盈利。
状态转移方程如下:
f[i,j]=max{f[i-1,j]+g[n-(i-j)+1,i],f[i-1,j-1]+g[j,i]}
其中g[i,j]表示田忌的马和齐王的马分别按照由强到弱的顺序排序之后,田忌的第i匹马和齐王的第j匹马赛跑所能取得的盈利,胜为200,输为-200,平为0。
--------------分割线-----------------------------------------
俩数组 ,排序,l1=1; l2=1; r1=n; r2=n;
( 左向右 如果 a[l1]>b[l2] 则 l1:=l1+1; l2:=l2+1; ans:=ans+200;
右往左 如果 a[r1]>b[r2] 则 r1:=r1-1; r2:=r2-1; ans:=ans+200;
此时如果 a[l1]=b[r2] 则中间的数全相等,不用算了。。
如果 a[l1]<b[r2] 则 s:=s-200; l1:=l1+1; r2:=r2-1;)
继续() 的循环;
证明:
得到从左往右第一个 a[l1]<=b[l2] 和从右往左第一个 a[r1]<=b[r2] 时,
草稿纸上演算一下就知道。。此时不管b[l2]是否等于a[l1] b[r2]是否等于a[r1] 让a[l1]和b[r2] 比赛 总是最好情况之一;
-------------------------rzy------------
稍作简单分析
既可以知道如果自己最强的马打不过齐王的马就派出自己最弱的马
如果打的过的话就去把它灭了
这样一分析,就可以知道 只能从头尾取马
那就转换成了常见的dp的线性模型,类似于矩阵取数的题目了
方程就自然而然的出来了
f[i,j]=max{f[i-1,j]+g[n-(i-j)+1,i],f[i-1,j-1]+g[j,i]}
(小心j=0 和j=i 的情况。。我刚开始就这里挂掉了)
--------------------------------------------
贪心
1.当田忌最慢的马比齐王最慢的马快,赢一场先。因为始终要赢齐王最慢的马,不如用最没用的马来赢它。
2.当田忌最慢的马比齐王最慢的马慢,和齐王最快的马比,输一场。因为田忌最慢的马始终要输的,不如用它来消耗齐王最有用的马。
3.当田忌最慢的和齐王最慢的马慢相等时,分4和5讨论。
4.当田忌最快的马比齐王最快的马快时,赢一场先。因为最快的马的用途就是来赢别人快的马,别人慢的马什么马都能赢。
5.当田忌最快的马比齐王最快的马慢时,拿最慢的马和齐王最快的马比,输一场,因为反正要输一场,不如拿最没用的马输。
6.当田忌最快的马和齐王最快的马相等时,这就要展开讨论了,贪心方法是,拿最慢的马来和齐王最快的马比.
显然是正确的!!!
//--------------------
这里讨论另外一种方程形式:
先排序后肯定从两头取,这个问题上面大神都解释清了(我很弱小解释不能)……
既然从田忌马队两头取,那么可以用一个区间[l,r]表示田忌当前可选的马队,取l或者取r,这样剩下的区间就是[l+1,r]或者[l,r-1]
齐王的马可以利用田忌区间算出来,田忌区间长度是r-l+1,所以赛过n-(r-l+1)场,由此齐王当前的马就是n-(r-l+1)+1=n-r+l
这样方程就有了(递归运行记忆化,别的方法不会……不过应该循环也能写?):
pick(l,r)=max(pick(l+1,r)+g[l,n-r+l],pick(l,r-1)+g[r,n-r+l])
其实原理都差不多来着吧…………只是个人觉得这样好理解些…………
//copy //greedy
#include <cstdio>
#include <algorithm>
using namespace std;
const int M=;
int qt[][M];
int n;
int main()
{
scanf("%d",&n);
for (int i=;i>=;i--)
for (int j=;j<=n;j++)
scanf("%d ",&qt[i][j]);
int s=;
sort(qt[]+,qt[]+n+,[](int a,int b){ return a<b; });
sort(qt[]+,qt[]+n+,[](int a,int b){ return a<b; });
int i1=,i2=n,j1=,j2=n;
while (i1<=i2)
if (qt[][i1]<qt[][j1]) {i1++;j1++;s++;continue;} else
if (qt[][i1]>qt[][j1]) {s--;j1++;i2--;continue;} else
if (qt[][i1]==qt[][j1])
if (qt[][i2]<qt[][j2]) {i2--;j2--;s++;continue;} else {if (qt[][j1]<qt[][i2]) s--;j1++;i2--;continue;}
printf("%d",s*);
return ;
} //dp
#include <iostream>
#include <algorithm>
#include <cstring>
#define N 1005
using namespace std; int n, a[N], b[N];
int f[N][N];
/*
不妨设齐王的马是从快到慢出场的。
f[l][r]: 在田忌的可选区间为[l, r]的时候,能得到的最大奖金,此时已经赛过n - (r - l + 1)场,故此时出场的是齐王的第n - r + l匹马
f[l][r] = max (f[l + 1][r] + g (l, n - r + l), f[l][r - 1] + g (r, n - r + l))
田忌选最快的马 田忌选最慢的马
*/ inline int g (int x, int y)
{
if (a[x] < b[y])
return -;
if (a[x] > b[y])
return ;
return ;
} int work (int l, int r)
{
if (f[l][r] != -)
return f[l][r];
if (l == r)
return f[l][r] = g (l, n); f[l][r] = max (work (l + , r) + g (l, n - r + l), work (l, r - ) + g (r, n - r + l));
return f[l][r];
} bool cmp (int x, int y)
{ return x > y; } int main()
{
cin >> n;
for (int i = ; i <= n; i++)
cin >> a[i];
for (int i = ; i <= n; i++)
cin >> b[i]; sort (a + , a + n + , cmp);
sort (b + , b + n + , cmp);
memset (f, -, sizeof (f)); cout << work (, n) << endl;
return ;
}
tyvj1048 田忌赛马的更多相关文章
- [POJ2287][Tyvj1048]田忌赛马 (贪心+DP)
瞎扯 很经典的一道题 考前才打 我太菜了QAQ 就是先贪心排序了好 然后在DP 这样比直接DP更容易理解 (其实这题做法还有很多) 代码 #include<cstdio> #include ...
- nyoj 364 田忌赛马(贪心)
田忌赛马 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 Here is a famous story in Chinese history. "That ...
- [codevs2181]田忌赛马
[codevs2181]田忌赛马 试题描述 中国古代的历史故事"田忌赛马"是为大家所熟知的.话说齐王和田忌又要赛马了,他们各派出N匹马,每场比赛,输的一方将要给赢的一方200两黄金 ...
- ACM 田忌赛马
田忌赛马 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 Here is a famous story in Chinese history. "That ...
- TYVJ P1048 田忌赛马 Label:dp
描述 中国古代的历史故事“田忌赛马”是为大家所熟知的.话说齐王和田忌又要赛马了,他们各派出N匹马,每场比赛,输的一方将要给赢的一方200两黄金,如果是平局的话,双方都不必拿出钱.现在每匹马的速 ...
- HDUOJ-------1052Tian Ji -- The Horse Racing(田忌赛马)
Tian Ji -- The Horse Racing Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (J ...
- D - D 田忌赛马
D - D 田忌赛马 解题报告 hdu 1052 Tian Ji -- The Horse Racing 链接:http://acm.hust.edu.cn/vjudge/contest/v ...
- HDOJ-1052 田忌赛马(贪心)
田忌赛马 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述: Here is a famous story in Chinese history. "That was ...
- [洛谷P1650] 田忌赛马
贪心难题:总结贪心问题的一般思路 传送门:$>here<$ 题意 田忌和齐王各有n匹马,赛马时一一对应.赢+200,输-200,平+0. 问最多多少钱? 数据范围:$n \leq 2000 ...
随机推荐
- [转] 前端开发利器--Brackets 的七种武器和旁门左道
转自:http://www.jianshu.com/p/ff7798aa4548 Brackets是Adobe开发的web编辑器,是一款免费开源.多平台支持的软件,并在于GitHub上维护.Brack ...
- 《百词斩·象形9000》第一册(上) 符号Symbol 1
001-upon prep. 在......上面 Wish upon a star.#对着星星许愿. 002-think V. 想,思索,认为:以为,预料 What do you think?#你认为 ...
- devstack环境搭建
1. devstack部署 参考Quick Start,推荐使用ubuntu16.04进行安装 1.1 配置ubuntu国内源 修改/etc/apt/sources.list内容为 deb http: ...
- lintcode-117-跳跃游戏 II
117-跳跃游戏 II 给出一个非负整数数组,你最初定位在数组的第一个位置. 数组中的每个元素代表你在那个位置可以跳跃的最大长度. 你的目标是使用最少的跳跃次数到达数组的最后一个位置. 样例 给出数组 ...
- IntelliJ IDEA 创建maven项目
说明 创建Maven项目的方式:手工创建 好处:参考IntelliJ IDEA 14 创建maven项目二(此文章描述了用此方式创建Maven项目的好处)及idea14使用maven创建web工程(此 ...
- Zebra - zebra command to get printer error and warning status
1 Flag2 Nibble 16-93 Nibble 8-44 Nibble 35 Nibble 26 Nibble 1
- [剑指Offer] 21.栈的压入、弹出序列
题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序 ...
- 【其他】Windows 系统安装IIS 打开页面出现空白解决方案
部署IIS过程中遇到了一个奇怪的问题,就是怎么设置打开的页面都是一篇空白,IIS也没有任何报错,翻遍互联网好不容易找到了解决方法,今天就教给大家,希望大家不要走弯路.此方法Windows xp.7.8 ...
- Session接口常用方法
org.hibernate.Session接口 beginTransaction 开启事务 clear 清缓存 close 关闭session connection - 过时 获取Connection ...
- 【bzoj1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+权值线段树合并
题目描述 求一张图的严格次小生成树的边权和,保证存在. 输入 第一行包含两个整数N 和M,表示无向图的点数与边数. 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z ...