田忌赛马 [贪心(完成) / 动态规划(待填坑)]

田 忌 赛 马 田忌赛马

题目见链接 .


最 初 想 法 \color{blue}{最初想法}

F [ i , j ] F[i, j] F[i,j] 表示前 i i i 场比赛, 使用的马属于前 j j j 匹马的最大收获,
F [ i , j ] = max ⁡ ( F [ i , j − 1 ] , F [ i − 1 , j − 1 ] + c o s t j ) F[i, j] = \max(F[i, j-1], F[i-1, j-1]+cost_j) F[i,j]=max(F[i,j1],F[i1,j1]+costj),
但是这样 d p dp dp 不能覆盖所有情况, 决策时只考虑了 选择前 j j j 匹马 .


正 解 部 分 \color{red}{正解部分}

  • 当田忌最快的马 快于 齐王最快的马, 直接赢 .

Q : Q: Q: 为什么不使用刚好快于齐王最快的马?
A : A: A: 因为若两匹马同时大于齐王最快的马时, 这两匹马都大于齐王的任何一匹马, 使用哪个没有区别 .

  • 当田忌最快的马 慢于 王最快的马, 拿最慢的马抵掉 王 最快的马 .
  • 当田忌最快的马 等于 王最快的马, 有两个选择,
    1. 使用最慢的马输掉 .
    2. 使用最快的马平局 .

Q : Q: Q: 第三个分支如何选择 ?
A : A: A: 看情况, 具体来说 ↓ ↓ ,

  • 若最慢的马可以赢掉王的其中一个马,

    1. 选择序号 2 2 2, 最慢的马赢可以得到 200 200 200 金币, 最快的马平局 ,
      总得失: 得到 200 200 200 金币 .
    2. 选择序号 1 1 1, 最慢的马输掉得到 − 200 -200 200 金币, 那个最快的马到后面会赢, 可能平局,
      就算最快的马赢了, 得到 200 200 200 金币,
      总得失: 得到 0 0 0 金币 .

    综上所述, 若最慢的马可以赢掉王的其中一匹马, 就拿最慢的马去赢, 最快的马去平 .

  • 若最慢的马不可以赢掉王的任何一个马,

    1. 选择序号 1 1 1, 得到 − 200 -200 200, 最快马可能会赢, 也可能平局,
      总得失: [ − 200 , 0 ] [-200, 0] [200,0]
    2. 选择序号 2 2 2, 得到 0 0 0, 最慢的那匹马一定会输, 得到 − 200 -200 200,
      总得失: − 200 -200 200.

    选择序号 1 1 1, 还有赚钱的希望,
    综上所述, 若最慢的马不可以赢掉王的任何一个马, 就拿最慢的马去浪费掉王的最快马 .

由于每场比赛田忌随意择马, 所以为了更方便处理, 先将齐王的马从大到小排序, 对答案没有影响 .


d p dp dp 的方法就待填坑吧…
咕咕咕


实 现 部 分 \color{red}{实现部分}

#include<bits/stdc++.h>
#define reg register

int N;
int A[2005];
int B[2005];

void Work(){
        scanf("%d", &N);
        for(reg int i = 1; i <= N; i ++) scanf("%d", &A[i]);
        for(reg int i = 1; i <= N; i ++) scanf("%d", &B[i]);
        std::sort(A+1, A+N+1), std::sort(B+1, B+N+1);
        int la = 1, ra = N, lb = 1, rb = N;
        int Ans = 0;
        while(la <= ra){
                if(A[ra] > B[rb]) ra --, rb --, Ans += 200;
                else if(A[ra] < B[rb]) la ++, rb --, Ans -= 200;
                else if(A[la] > B[lb]) la ++, lb ++, Ans += 200; 
                else{
                        if(A[la] < B[rb]) Ans -= 200; // !!!
                        la ++, rb --;
                }
        }
        printf("%d\n", Ans);
}

int main(){
        int T = 1;
//        scanf("%d", &T);
        while(T --) Work();
        return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值