算法分析:

这个问题很显然可以转化成一个二分图最佳匹配的问题。把田忌的马放左边,把齐王的马放右边。田忌的马A和齐王的B之间,如果田忌的马胜,则连一条权为200的边;如果平局,则连一条权为0的边;如果输,则连一条权为-200的边。 然而我们知道,二分图的最佳匹配算法的复杂度很高,无法满足N=2000的要求。 我们不妨用贪心思想来分析一下问题。因为田忌掌握有比赛的“主动权”,他总是根据齐王所出的马来分配自己的马,所以这里不妨认为齐王的出马顺序是按马的速度从高到低出的。由这样的假设,我们归纳出如下贪心策略:

 1、如果田忌剩下的马中最强的马都赢不了齐王剩下的最强的马,那么应该用最差的一匹马去输给齐王最强的马。  2、如果田忌剩下的马中最强的马可以赢齐王剩下的最强的马,那就用这匹马去赢齐王剩下的最强的马。   3、如果田忌剩下的马中最强的马和齐王剩下的最强的马打平的话,可以选择打平或者用最差的马输掉比赛。

第一个贪心策略的证明: 此时田忌的所有马都赢不了齐王的马,所以无论用最慢马去输还是用最快的马去输都同样是输,而处于贪心的思想,我们应该保留相比之下更强的马,因此用最慢的马去输一定不会比用别的马去输来得劣,所以这是最优策略。 证毕。

第二个贪心策略的证明: 假设现在齐王剩下的最强的马是A,田忌剩下的最强的马是B,如果存在一种更优的比赛策略,让B的对手不是A,而使得田忌赢更多的钱的话,那么设此时A的对手是b,B的对手是a: 1、 若b>A,则有B>a,b>A。这个结果和B>A,b>a是相同的。 2、 若a<b≤A,则有B>a,b≤A。这个结果不如B>A,b>a来得优秀。 3、 若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。 本题小结: 虽然本题存在直接贪心的方法,不过它可以作为一个例子告诉大家,合理的运用贪心策略,分析出问题的一些本质之后,一些看似不能用动态规划做的题目便可以巧妙的确立出状态,继而可以用动态规划来求解。

补充:对于状态转移方程

f[i][j]=max(f[i-1][j]+g[n-(i-j)+1][i],f[i-1][j-1]+g[j][i]);

还应该有两种特殊一点的情况

1 进行到第i场比赛的时候,从头取了0匹马,那么所有的马均为从尾取的, 则f[i][j]=f[i-1][j]+g[n-(i-j)+1][i];

其中n-(i-j)+1表示从尾取的第(i-j)匹马在整个排好顺序的马中是第几匹马

例如 共有8匹马, 进行到第4场比赛的时候,从头取了0匹马,表示要从尾取4匹马

1 2 3 4   5 6 7 8

即要取编号为5的这匹马,5=8-(4-0)+1; 那么f[4][0]=f[3][0]+g[8-(4-0)+1][4]

2 进行到第i场比赛的时候,从头取了i匹马,表明一直都是从头取的马 f[i][j]=f[i-1][j-1]+g[j][i];

Tian Ji -- The Horse Racing

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 19321    Accepted Submission(s): 5641

Problem Description
Here is a famous story in Chinese history.
"That was about 2300 years ago. General Tian Ji was a high official in the country Qi. He likes to play horse racing with the king and others."
"Both of Tian and the king have three horses in different classes, namely, regular, plus, and super. The rule is to have three rounds in a match; each of the horses must be used in one round. The winner of a single round takes two hundred silver dollars from the loser."
"Being the most powerful man in the country, the king has so nice horses that in each class his horse is better than Tian's. As a result, each time the king takes six hundred silver dollars from Tian."
"Tian Ji was not happy about that, until he met Sun Bin, one of the most famous generals in Chinese history. Using a little trick due to Sun, Tian Ji brought home two hundred silver dollars and such a grace in the next match."
"It was a rather simple trick. Using his regular class horse race against the super class from the king, they will certainly lose that round. But then his plus beat the king's regular, and his super beat the king's plus. What a simple trick. And how do you think of Tian Ji, the high ranked official in China?"

Were Tian Ji lives in nowadays, he will certainly laugh at himself. Even more, were he sitting in the ACM contest right now, he may discover that the horse racing problem can be simply viewed as finding the maximum matching in a bipartite graph. Draw Tian's horses on one side, and the king's horses on the other. Whenever one of Tian's horses can beat one from the king, we draw an edge between them, meaning we wish to establish this pair. Then, the problem of winning as many rounds as possible is just to find the maximum matching in this graph. If there are ties, the problem becomes more complicated, he needs to assign weights 0, 1, or -1 to all the possible edges, and find a maximum weighted perfect matching...
However, the horse racing problem is a very special case of bipartite matching. The graph is decided by the speed of the horses --- a vertex of higher speed always beat a vertex of lower speed. In this case, the weighted bipartite matching algorithm is a too advanced tool to deal with the problem.
In this problem, you are asked to write a program to solve this special case of matching problem.
 
Input
The input consists of up to 50 test cases. Each case starts with a positive integer n (n <= 1000) on the first line, which is the number of horses on each side. The next n integers on the second line are the speeds of Tian’s horses. Then the next n integers on the third line are the speeds of the king’s horses. The input ends with a line that has a single 0 after the last test case.
 
Output
For each input case, output a line containing a single number, which is the maximum money Tian Ji will get, in silver dollars.
 
Sample Input
3
92 83 71
95 87 74
2
20 20
20 20
2
20 19
22 18
0
 
Sample Output
200
0
0
 
#include<stdio.h>
#include<string.h>
int tian[1005],king[1005],g[1005][1005],f[1005][1005];
void bubblesort(int a[],int n)
{
int i,j,t;
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)
{
if(a[i]<a[j])
{
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
}
} int max(int a,int b)
{
if(a>b)
return a;
else
return b;
}
int main()
{
int n,i,j,maxx;
while(scanf("%d",&n)!=EOF&&n) //输入为0的 时候结束输入
{
for(i=1;i<=n;i++)
scanf("%d",&tian[i]);
for(i=1;i<=n;i++)
scanf("%d",&king[i]);
memset(g,0,sizeof(g));
memset(f,0,sizeof(f));
bubblesort(king,n);
bubblesort(tian,n); for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(tian[i]>king[j])
g[i][j]=200;
else if(tian[i]<king[j])
g[i][j]=-200;
else
g[i][j]=0;
}
} for(i=1;i<=n;i++)
{
for(j=0;j<=i;j++)
{
if(j==0)
f[i][j]=f[i-1][j]+g[n-(i-j)+1][i];
else if(i==j)
f[i][j]=f[i-1][j-1]+g[j][i];
else
f[i][j]=max(f[i-1][j]+g[n-(i-j)+1][i],f[i-1][j-1]+g[j][i]);
}
}
maxx=-200005;
for(j=0;j<=n;j++)
{ if(f[n][j]>maxx)
maxx=f[n][j]; }
printf("%d\n",maxx);
}
}

  

HDU 1052 Tian Ji -- The Horse Racing【贪心在动态规划中的运用】的更多相关文章

  1. HDU 1052 Tian Ji -- The Horse Racing(贪心)

    题目来源:1052 题目分析:题目说的权值匹配算法,有点误导作用,这道题实际是用贪心来做的. 主要就是规则的设定: 1.田忌最慢的马比国王最慢的马快,就赢一场 2.如果田忌最慢的马比国王最慢的马慢,就 ...

  2. HDU 1052 Tian Ji -- The Horse Racing (贪心)(转载有修改)

    Tian Ji -- The Horse Racing Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (J ...

  3. Hdu 1052 Tian Ji -- The Horse Racing

    Tian Ji -- The Horse Racing Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (J ...

  4. hdu 1052 Tian Ji -- The Horse Racing (田忌赛马)

    Tian Ji -- The Horse Racing Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (J ...

  5. HDU 1052 Tian Ji -- The Horse Racing(贪心)(2004 Asia Regional Shanghai)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1052 Problem Description Here is a famous story in Ch ...

  6. hdu 1052 Tian Ji -- The Horse Racing【田忌赛马】

    题目 这道题主要是需要考虑到各种情况:先对马的速度进行排序,然后分情况考虑: 1.当田忌最慢的马比国王最慢的马快则赢一局 2.当田忌最快的马比国王最快的马快则赢一局 3.当田忌最快的马比国王最快的马慢 ...

  7. 杭州电 1052 Tian Ji -- The Horse Racing(贪婪)

    http://acm.hdu.edu.cn/showproblem.php? pid=1052 Tian Ji -- The Horse Racing Time Limit: 2000/1000 MS ...

  8. hdoj 1052 Tian Ji -- The Horse Racing【田忌赛马】 【贪心】

    思路:先按从小到大排序, 然后从最快的開始比(如果i, j 是最慢的一端, flag1, flag2是最快的一端 ),田的最快的大于king的 则比較,如果等于然后推断,有三种情况: 一:大于则比較, ...

  9. POJ-2287.Tian Ji -- The Horse Racing (贪心)

    Tian Ji -- The Horse Racing Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 17662   Acc ...

随机推荐

  1. [Shell] echo/输出 中引用命令

    # 这样是错误的,是引用变量 echo "/Users/${whoami}/Desktop" >>> /Users//Desktop # 正确的写法应该是使用`` ...

  2. 洛谷P1563 玩具谜题 简单模拟

    没意义,注意方向别判错. Code: #include<cstdio> #include<cstring> using namespace std; const int max ...

  3. nginx的headers_more模块的使用

    nginx的headers_more模块用于 添加.修改或清除 请求/响应头,该模块不是nginx自带的,默认不包含该模块,需要另外安装.幸运的是openresty默认包含了该模块,可以直接使用. 该 ...

  4. 【disconf】环境搭建【linux】

     1.搭建disconf需要安装的配置. 安装Linux:CentOS7     安装Zookeeper:zookeeper-3.4.6     安装Redis:redis-3.0.0     安装N ...

  5. 【JavaScript框架封装】在实现一个自己定义类似于JQuery的append()函数的时候遇到的问题及解决方案

    主要问题: 在刚开始创建了这个函数之后,使用的时候,总是会出现一个问题,就是按照正常步骤给一个ID选择器添加子节点的时候正常,但是到了给一个class选择器的元素添加的时候始终只能添加一个. 下面是我 ...

  6. MAVEN 的常用命令

    1.清除命令:mvn clean 2.编译命令:mvn  conpile 3.打包命令:mvn package 4.跳过单元测试命令:mvn clean package -Dmaven.test.sk ...

  7. 基于Vue的事件响应式进度条组件

    写在前面 找了很多Vue 进度条组件!,都不包含拖拽和点击事件,input range倒是原生包含input和change事件,但是直接基于input range做进度条的话,样式部分需要做大量调整和 ...

  8. 2.SSH 两个表全套增删改(运动员住宿管理)

    0.创建如下oracle的命令 create table HOTALINFO ( HOTALID ) not null, HOTALNAME ) not null, HOTALADDRESS ) no ...

  9. socketserver模块初识

    python提供了两个级别访问的网络服务: 低级的网络服务支持基本的socket,它提供了标准的BSD sockets API,可以访问底层操作系统socket接口的全部方法 高级别的网络服务模块so ...

  10. 关于错误CSC : error CS0006:未能找到元数据文件

    在不同的解决方案中把一个项目搬来搬去,终于出现了传说的CSC : error CS0006.编译的时候总是提示一个引用中不存在的项找不到.无论怎样删除项目,删除引用都没法通过生成. 最终解决方案: 用 ...