解决SPOJ Diehard的正确方法是什么?

What is the correct approach to solve SPOJ DIEHARD?

本文关键字:方法 是什么 SPOJ Diehard 解决      更新时间:2023-10-16

我试图在spoj https://www.spoj.pl/problems/diehard/上解决一个练习问题。但是,我的贪婪方法都导致错误的答案和递归对最坏的情况来说太慢了。有人可以告诉如何解决这个问题吗?我正在寻找有人指向正确的方向。

游戏很简单。最初,您拥有" H"量的健康和" A"装甲量。在任何瞬间,您都可以住在三个地方中的任何一个 - 火,水和空气。每次单位之后,您都必须改变自己的生活地点。例如,如果您目前居住在火中,则可以踏入水或空气。

  • 如果您踏入空中,您的健康状况会增加3,并且您的装甲增加2
  • 如果您踏入水中,您的健康状况会降低5,盔甲降低10
    如果您着火了,您的健康状况会减少20,而您的装甲增加了5

如果您的健康或装甲变为< = 0,您将立即死亡

找到您可以生存的最长时间。

输入:

第一行由整数T组成,即测试用例的数量。对于每个测试案例,将有两个代表初始健康h和初始装甲a的正整数。

输出:

对于每个测试案例,找到您可以生存的最长时间。

好吧,首先尝试通过贪婪的方法解决它。很明显,由于增加了装甲和健康,空气是最佳选择,但您只能交替去空中。因此,每个奇数(即1,3,5 ...)的移动都将是播出的。现在我们必须决定如何处理偶数?

所以我们有两种选择射击还是水?我们必须是合理的,并选择这样的举动,以保持H和A高于0。t您的健康> 0。因此,如果H> 5和a> 10选择水。

现在,如果我们没有装甲但健康状况足够怎么办?在这种情况下,我们别无选择,只能跳火。

所以现在我们有了一种贪婪的方法:

因此,如果我们有足够的H和A,我们将去水。否则,如果H足够足够并且A还不够,请点燃。否则,已经结束了!

这是实现的界面链接:http://ideone.com/rkobnk

#include<stdio.h>
int main(){
    long long int x,i,a,b,t,h,arm;
    scanf("%lld",&x);
    for(i=0;i<x;i++){
        scanf("%lld %lld",&a,&b);
        if(a==0||b==0)
         printf("0n");
        else{
            t=1;
            h=a+3;
            arm=b+2;
            while(1){
                if(h>5&&arm>10){
                    h=h-2;
                    arm=arm-8;
                    t=t+2;
                }else if(h>20&&arm<=10){
                    h=h-17;
                    arm=arm+7;
                    t=t+2;
                }else {
                    printf("%lldn",t);
                    break;
                }
            }
     }
    }
    return 0;
} 

这是通过分析进行操作的另一种方法:

a = number of times visiting air state
F = number of times visiting fire state
W = number of times visiting water state
M = a + F + W  // total moves
// positive
a >= 0
F >= 0
W >= 0
// because of the restriction of moving between states...
a <= F + W + 1
F <= W + a + 1
W <= a + F + 1
// the effect of armor and health...
H < -3a + 5H + 20F
A < -2a + 10W - 5F

最大化M。您可以通过二进制搜索M进行M。

二进制搜索循环:

int ok = 0;
int impossible = 1000000000;
while (impossible - ok > 1)
{
    int candidate = ok + (impossible-ok) / 2;
    if (check(candidate))
        ok = candidate;
    else
        impossible = candidate;
}
return ok;

无论哪种情况,都使用基本高中代数来简化不平等/方程。

i通过使用动态进程来完成。DP [Health] [Armour] [Air/Fire/Water] - 如果您从这种情况开始然后,复发状况简单地变成DP [Health] [Armour] [空气/消防/水] = 1 下一个状态的最大显而易见的基本情况是他无处可去的时候,所以答案变为零。

您是否尝试过DFS?状态是(空气|火|水,h,a)的元组。这有:

3 * 1000 * 1000 = 3,000,000 game states

在上面做DFS并找到最高的动作。(即将所有内容都设置为-1,然后将初始状态设置为0,然后将DFS从0到所有可及的位置)