8

I was trying to solve a practice question on SPOJ https://www.spoj.pl/problems/DIEHARD/ . However both my greedy approach resulted in Wrong Answer and recursion was too slow for the worst case.Can anyone tell how to approach this problem? I am looking for someone to point me in the right direction.

The game is simple. You initially have ‘H’ amount of health and ‘A’ amount of armor. At any instant you can live in any of the three places - fire, water and air. After every unit time, you have to change your place of living. For example if you are currently living at fire, you can either step into water or air.

  • If you step into air, your health increases by 3 and your armor increases by 2
  • If you step into water, your health decreases by 5 and your armor decreases by 10
    If you step into fire, your health decreases by 20 and your armor increases by 5

If your health or armor becomes <=0, you will die instantly

Find the maximum time you can survive.

Input:

The first line consists of an integer t, the number of test cases. For each test case there will be two positive integers representing the initial health H and initial armor A.

Output:

For each test case find the maximum time you can survive.

Colonel Panic
  • 132,665
  • 89
  • 401
  • 465
user1724072
  • 331
  • 1
  • 3
  • 8

4 Answers4

6

Okay, Firstly try solving it by greedy approach. It is obvious that air is the best choice possible as it increases both armor and health but you can go to air alternately only. So every odd(i.e 1,3,5...) move will be to air. Now we have to decide what to do with even moves?

So we have two choices Fire or water? We have to be reasonable and choose such a move that keeps both H and A above 0. Now jumping in fire costs health -20 even though it increases armor by 5, but hey wait, what is the use of increased armor if you don't get your health >0 . So if H>5 and A>10 choose water.

Now what if we are short of armor but have enough health? In that case we have no choice but to jump to fire.

So now we have a greedy approach:

So, if we have sufficient H and A, we'll go to water. Else, if H is sufficient enough and A is not sufficient, go to fire. Else, it's over!

Here is the ideone link of implementation: 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("0\n");
        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("%lld\n",t);
                    break;
                }
            }
     }
    }
    return 0;
} 
Kartik Bhatia
  • 71
  • 1
  • 8
  • 1
    In the else if condition you need not to check for arm<=10 because if h>20 is true it means if part went false because arm was <=10. – Ritika Gupta Feb 19 '21 at 08:36
1

Here is another way to do it analytically:

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

Maximize M. You can do this by binary searching for M, or you can use linear programming.

Binary search loop:

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;

In either case use basic high school algebra to simplify the inequalities/equation.

Andrew Tomazos
  • 66,139
  • 40
  • 186
  • 319
  • Can you detail how to binary search `M`? In what interval, and what do you do for a given candidate value `k` in that interval? – IVlad Oct 19 '12 at 15:41
  • Well 0 is always ok and 10^9 is always impossible, so that's your interval. For a fixed M you need to decide whether M is ok or impossible. Manipulate the inequalities using algebra to do this. – Andrew Tomazos Oct 19 '12 at 15:50
  • How efficiently can you compute `check`? I can't see a way to do it much better than the brute force. – IVlad Oct 19 '12 at 17:28
  • You have 6 equations in 3 unknowns (a,F,W). Recall that M, H and A are now constant. It is high school algebra. (constant time) – Andrew Tomazos Oct 20 '12 at 04:42
  • You don't have 6 equations, you have one equation and at least 3 inequalities. – IVlad Oct 20 '12 at 08:42
  • That's what I meant. Solve the first for a (`a = M + F + W`), substitute out a, leaving 2 unknowns (F,W) - and so on. – Andrew Tomazos Oct 20 '12 at 10:14
1

I did by using dynamic progamming. Dp[health][armour][air/fire/water]- is the maximum time you can live if you start from this condition then the recurrent conditions simply become Dp[health][armour][air/fire/water]=1+max of the next states you can go to Obviousy the base case is when he can go nowhere so the answer for that becomes zero.

Aman Gupta
  • 557
  • 1
  • 8
  • 23
0

Have you tried DFS? The state is a tuple of (air|fire|water, H, A). This has:

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

Do a DFS on it and find the highest moves. (ie set everything to -1 and the initial states to 0, then DFS from 0 states to all reachable positions)

Andrew Tomazos
  • 66,139
  • 40
  • 186
  • 319
  • :What should be the source and destination vertex for this problem ? – user1724072 Oct 19 '12 at 14:45
  • The source is the inital states. The array keeps track of the highest number of moves to reach that state. – Andrew Tomazos Oct 19 '12 at 14:49
  • Actually it is a little more complicated than I have let on but the general approach should work. – Andrew Tomazos Oct 19 '12 at 14:50
  • :I have already tried a lot.Most people have soled this question in 0.00s ,so i think it might be a lot more easier. – user1724072 Oct 19 '12 at 14:58
  • Well there is an analytic solution. The order you visit the states is not important, so setup a system of linear inequalities and solve them with algebra. (Or you could binary search on them.) – Andrew Tomazos Oct 19 '12 at 15:20
  • @AndrewTomazos-Fathomling what do you mean the order you visit the states is not important? For example, it's easy to find an example that lets you survive more if you pick air first, because it increases both health and armor. – IVlad Oct 19 '12 at 15:40
  • @IVlad: No I mean the cost of visiting air, fire and water doesn't change depending on the order in which you visit it. So it is a sufficient statistic to simply ask how many times you visit each state. See my other answer. – Andrew Tomazos Oct 19 '12 at 15:54