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 ...
随机推荐
- Web框架本质及浅谈HTTP协议
Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web框架了. 半成品自定义web框架 impor ...
- CCF-NOIP-2018 提高组(复赛) 模拟试题(四)
T1 贪吃蛇 [问题描述] 贪吃蛇是一个好玩的游戏.在本题中,你需要对这个游戏进行模拟. 这个游戏在一个 \(n\) 行 \(m\) 列的二维棋盘上进行. 我们用 \((x, y)\) 来表示第 \( ...
- ardupilot_gazebo仿真(二)
ardupilot_gazebo仿真(二) 标签(空格分隔): 未分类 在模型中添加sensor gezebo官网-sensor部分教程 gezebo官网-基础部分教程 Gazebo plugins ...
- Python 3 学习笔记之——变量作用域、模块和包
1. 变量作用域 Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的.变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称.Python 的作用域一共 ...
- 传输控制层协议TCP概述---抄书
1.TCP的主要特点 TCP是TCP/IP体系中非常复杂的一个协议.下面介绍TCP的最主要的特点. (1)TCP是面向连接的运输层协议.也就是说,应用程序在使用TCP协议之前,必须先建立TCP连接.在 ...
- POJ 3177 Redundant Paths & POJ 3352 Road Construction(双连通分量)
Description In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numb ...
- wpa_supplicant 初始化
几个重要的结构体介绍: 1. struct wpa_interface --- Parameters for wpa_supplicant_add_iface(). wpa_interface对应网络 ...
- lintcode-124-最长连续序列
124-最长连续序列 给定一个未排序的整数数组,找出最长连续序列的长度. 说明 要求你的算法复杂度为O(n) 样例 给出数组[100, 4, 200, 1, 3, 2],这个最长的连续序列是 [1, ...
- 一个python游戏源码
#finalPyPong.py import pygame,sys class MyBallClass(pygame.sprite.Sprite): def __init__(self,image_f ...
- Java 对象及其内存控制
作者:禅楼望月(http://www.cnblogs.com/yaoyinglong) 更新:其实这里有好多的变戏法,只要你理解了他们在JVM的中的实现机制,就豁然开朗了.有时间我会把这些变戏法的东西 ...