算法分析:

这个问题很显然可以转化成一个二分图最佳匹配的问题。把田忌的马放左边,把齐王的马放右边。田忌的马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
 
  1. #include<stdio.h>
  2. #include<string.h>
  3. int tian[1005],king[1005],g[1005][1005],f[1005][1005];
  4. void bubblesort(int a[],int n)
  5. {
  6. int i,j,t;
  7. for(i=1;i<=n;i++)
  8. {
  9. for(j=i+1;j<=n;j++)
  10. {
  11. if(a[i]<a[j])
  12. {
  13. t=a[i];
  14. a[i]=a[j];
  15. a[j]=t;
  16. }
  17. }
  18. }
  19. }
  20.  
  21. int max(int a,int b)
  22. {
  23. if(a>b)
  24. return a;
  25. else
  26. return b;
  27. }
  28. int main()
  29. {
  30. int n,i,j,maxx;
  31. while(scanf("%d",&n)!=EOF&&n) //输入为0的 时候结束输入
  32. {
  33. for(i=1;i<=n;i++)
  34. scanf("%d",&tian[i]);
  35. for(i=1;i<=n;i++)
  36. scanf("%d",&king[i]);
  37. memset(g,0,sizeof(g));
  38. memset(f,0,sizeof(f));
  39. bubblesort(king,n);
  40. bubblesort(tian,n);
  41.  
  42. for(i=1;i<=n;i++)
  43. {
  44. for(j=1;j<=n;j++)
  45. {
  46. if(tian[i]>king[j])
  47. g[i][j]=200;
  48. else if(tian[i]<king[j])
  49. g[i][j]=-200;
  50. else
  51. g[i][j]=0;
  52. }
  53. }
  54.  
  55. for(i=1;i<=n;i++)
  56. {
  57. for(j=0;j<=i;j++)
  58. {
  59. if(j==0)
  60. f[i][j]=f[i-1][j]+g[n-(i-j)+1][i];
  61. else if(i==j)
  62. f[i][j]=f[i-1][j-1]+g[j][i];
  63. else
  64. f[i][j]=max(f[i-1][j]+g[n-(i-j)+1][i],f[i-1][j-1]+g[j][i]);
  65. }
  66. }
  67. maxx=-200005;
  68. for(j=0;j<=n;j++)
  69. {
  70.  
  71. if(f[n][j]>maxx)
  72. maxx=f[n][j];
  73.  
  74. }
  75. printf("%d\n",maxx);
  76. }
  77. }

  

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. IOS让自定义类是用下标

    在ios中,有个非常有用的特性,就是可以为自己写的类增加下标访问功能. 如果我们自己的类中有个数组items,我们想直接给类加下标的方式来访问这个数组的元素,就像访问系统的数组一样,其实只要增加一个方 ...

  2. 训练1-R

    给出一个长度为N的数组,进行Q次查询,查询从第i个元素开始长度为l的子段所有元素之和. 例如,1 3 7 9 -1,查询第2个元素开始长度为3的子段和,1 {3 7 9} -1.3 + 7 + 9 = ...

  3. freeswich 安装mod_av

    转载   https://www.cnblogs.com/zgen1/p/7867303.html 需要先编译libav库 编译libav下载:git clone https://freeswitch ...

  4. 《黑白团团队》第七次作业:团队项目设计完善&编码

    项目 内容 作业课程地址 任课教师首页链接 作业要求 团队项目 填写团队名称 黑白团团队 填写具体目标 认真负责,完成项目 任务1:团队软件项目设计完善 Github仓库上传<软件设计方案说明书 ...

  5. OA项目知识总结

    struts文件配置 --------------------------------------------------------- 配置c3po链接池 --------------------- ...

  6. smartctl----硬盘状态监控

    smartmontools介绍 smartmontools是一款开源的磁盘控制,监视工具,可以运行在Linux,Unix,BSD,Solaris,Mac OS,OS/2,Cygwin和Windows上 ...

  7. POJ 2184

    简单的01背包,把S看体积,把F看价值,把它们变正数处理就可以了.在处理负数时,因为减一个负数相当于加一个,所以要从前往后. #include <iostream> #include &l ...

  8. WifiManager类具体解释

    public class WifiManager extends Object java.lang.Object    ↳ android.net.wifi.WifiManager 类概述 This ...

  9. 验证DG最大性能模式下使用ARCH/LGWR及STANDBY LOG的不同情况

    总结:  --两台单实例数据库做DG,数据库版本号10.2.0.1.0 1.主库配置为:arch async,备库无STANDBY LOG. 日志中会有:RFS[4]: No standby redo ...

  10. cocos2dx --- 在游戏中显示HTML页面

    前文介绍了简单的富文本组件RichText,如今我们来了解下由freeType库做出来的第三方组件.可以直接显示html页面,而且可以实现超链接.和触摸事情. 步骤: 1.在github中  下载  ...