AOJ 0288 - Knocker of the Gigas Cedar

RE.Ω\ζ°)チーン.

解法

経験値は100より多くあっても意味がないことに注意する.
dp[i][j] := 樹の残りの耐久力がi,自分の経験値がjのときから何回で樹を倒せるか.
これはO(DN)(定数に100がつく)で更新できる.

コード

#include <cstdio>
#include <cstring>
#include <algorithm>

int D, N;
int dp[101][101];
int A[100], E[100], R[100];

int main(){
    while(scanf("%d %d", &D, &N), D || N){
        for(int i=0;i<N;i++){
            scanf("%d %d %d", A+i, E+i, R+i);
        }

        for(int i=0;i<=D;i++){
            for(int j=0;j<=100;j++){
                dp[i][j] = 1001001001;
            }
        }

        dp[D][0] = 0;
        for(int i=D;i>=0;i--){
            for(int j=0;j<=100;j++){
                for(int k=0;k<N;k++){
                    if(j >= R[k]){
                        int ni = std::max(i-A[k],0),
                            nj = std::min(j+E[k],100);
                        dp[ni][nj] = std::min(dp[ni][nj], dp[i][j] + 1);
                    }
                }
            }
        }

        int res = 1001001001;
        for(int i=0;i<=100;i++){
            res = std::min(res, dp[0][i]);
        }

        if(res != 1001001001){printf("%d\n", res);}
        else{puts("NA");}
    }