洛谷P1650赛马与codevs 2181 田忌赛马

洛谷P1650 赛马

题目描述

我国历史上有个著名的故事: 那是在2300年以前。齐国的大将军田忌喜欢赛马。他经常和齐王赛马。他和齐王都有三匹马:常规马,上级马,超级马。一共赛三局,每局的胜者可以从负者这里取得200银币。每匹马只能用一次。齐王的马好,同等级的马,齐王的总是比田忌的要好一点。于是每次和齐王赛马,田忌总会输600银币。

田忌很沮丧,直到他遇到了著名的军师――孙膑。田忌采用了孙膑的计策之后,三场比赛下来,轻松而优雅地赢了齐王200银币。这实在是个很简单的计策。由于齐王总是先出最好的马,再出次好的,所以田忌用常规马对齐王的超级马,用自己的超级马对齐王的上级马,用自己的上级马对齐王的常规马,以两胜一负的战绩赢得200银币。实在很简单。

如果不止三匹马怎么办?这个问题很显然可以转化成一个二分图最佳匹配的问题。把田忌的马放左边,把齐王的马放右边。田忌的马A和齐王的B之间,如果田忌的马胜,则连一条权为200的边;如果平局,则连一条权为0的边;如果输,则连一条权为-200的边……如果你不会求最佳匹配,用最小费用最大流也可以啊。 然而,赛马问题是一种特殊的二分图最佳匹配的问题,上面的算法过于先进了,简直是杀鸡用牛刀。现在,就请你设计一个简单的算法解决这个问题。

输入输出格式

输入格式:

第一行一个整数n,表示他们各有几匹马(两人拥有的马的数目相同)。第二行n个整数,每个整数都代表田忌的某匹马的速度值(0 <= 速度值<= 100)。第三行n个整数,描述齐王的马的速度值。两马相遇,根据速度值的大小就可以知道哪匹马会胜出。如果速度值相同,则和局,谁也不拿钱。

【数据规模】

对于20%的数据,1<=N<=65;

对于40%的数据,1<=N<=250;

对于100%的数据,1<=N<=2000。

输出格式:

仅一行,一个整数,表示田忌最大能得到多少银币。

输入输出样例

输入样例#1:

3

92 83 71

95 87 74

输出样例#1:

200

思路自己去问孙膑吧·················

或者田忌也行,毕竟用过············

齐威王就算了,他会揍你的·········

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<string>
 5 #include<cstring>
 6 #include<algorithm>
 7 using namespace std;
 8 
 9 int tot,n;
10 int a[2001],b[2001];
11 bool flag;
12 int h1,h2,t1,t2;
13 int main()
14 {
15     scanf("%d",&n);
16     for(int i=0;i<n;++i)
17         scanf("%d",&a[i]);
18     for(int i=0;i<n;++i)
19         scanf("%d",&b[i]);
20     sort(a,a+n);
21     sort(b,b+n);
22     t1=t2=n-1;
23     for(int i=0;i<n;++i)
24     {
25         if(a[t1]>b[t2])//最快的马比对手最快的马快
26         {
27             --t1;
28             --t2;
29             tot++;
30             continue;
31         }
32         if(a[h1]>b[h2])//最慢的马比对手最慢的马快
33         {
34             ++h1;
35             ++h2;
36             tot++;
37             continue;
38         }
39         if(a[t1]==b[h2])//最快的马速度与对手最慢的马相等 
40         {
41             --t1;
42             ++h2;
43             continue;
44         }
45         ++h1;
46         --t2;
47         tot--;//均不符合,用最慢的马消耗对手最快的马
48     }
49     printf("%d",tot*200);
50     return 0;
51 }
View Code

 

codevs上也有一道赛马题目,题目几乎一样,但如果把这份代码交上去会WA两个点(13和14)

2181 田忌赛马

 

时间限制: 1 s
空间限制: 32000 KB
题目等级 : 钻石 Diamond
题目描述 Description

    中国古代的历史故事“田忌赛马”是为大家所熟知的。话说齐王和田忌又要赛马了,他们各派出N匹马,每场比赛,输的一方将要给赢的一方200两黄金,如果是平局的话,双方都不必拿出钱。现在每匹马的速度值是固定而且已知的,而齐王出马也不管田忌的出马顺序。请问田忌该如何安排自己的马去对抗齐王的马,才能赢取最多的钱?

输入描述 Input Description

第一行为一个正整数n ,表示双方马的数量。
第二行有N个整数表示田忌的马的速度。
第三行的N个整数为齐王的马的速度。

输出描述 Output Description

仅有一行,为田忌赛马可能赢得的最多的钱,结果有可能为负。

样例输入 Sample Input

3
92 83 71
95 87 74

样例输出 Sample Output

200

数据范围及提示 Data Size & Hint

n <= 1000

第13个点:

你的答案

< -400000
\ No newline at end of file

正确答案

> 0

输入数据 (只显示前20行,完整数据请点击上面按钮下载)

2000
610 871 837 394 984 484 862 976 366 235 294 235 156 208 415 144 313 639 443 779 824 280 464 570 669 25 837 869 262 952 359 840 809 610 1 440 591 319 976 501 14 18 682 190 732 428 992 1 749 69 926 66 136 372 270 629 88 219 855 912 148 163 880 906 560 783 829 939 929 649 265 810 946 511 296 812 323 726 547 761 809 989 803 41 538 34 921 88 240 102 142 582 15 197 940 217 730 556 937 84 408 279 595 202 772 271 880 797 352 536 839 371 972 703 434 924 186 304 377 470 54 372 547 625 731 325 605 970 561 335 601 983 394 997 878 469 431 859 573 555 261 833 656 584 56 67 68 214 517 338 228 520 990 842 829 337 363 609 776 270 875 532 125 990 981 954 605 838 156 956 537 237 458 702 594 455 446 307 593 873 692 887 538 360 445 979 734 333 82 376 546 133 161 210 953 580 642 542 372 899 354 215 382 322 49 120 52 334 367 911 220 613 615 200 633 548 68 89 719 467 362 332 803 447 241 360 984 250 128 48 840 812 728 612 71 706 816 660 663 331 721 837 990 236 832 178 709 375 746 513 778 117 114 94 624 997 827 61 461 921 580 735 ...

改后代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;

int tot,n;
int a[2001],b[2001];
bool flag;
int h1,h2,t1,t2;
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;++i)
        scanf("%d",&a[i]);
    for(int i=0;i<n;++i)
        scanf("%d",&b[i]);
    sort(a,a+n);
    sort(b,b+n);
    t1=t2=n-1;
    for(int i=0;i<n;++i)
    {
        if(a[t1]>b[t2])//最快的马比对手最快的马快
        {
            --t1;
            --t2;
            tot++;
            continue;
        }
        if(a[h1]>b[h2])//最慢的马比对手最慢的马快
        {
            ++h1;
            ++h2;
            tot++;
            continue;
        }
        if(a[t1]==b[h2])//最快的马速度与对手最慢的马相等 
        {
            --t1;
            ++h2;
            continue;
        }
        ++h1;
        --t2;
        tot--;//均不符合,用最慢的马消耗对手最快的马
    }
    if(tot>0)printf("%d",tot*200);
    else printf("0");
    return 0;
}
View Code

说好的结果可能为负呢························

posted @ 2017-05-06 14:55  快乐永恒  阅读(500)  评论(0编辑  收藏  举报