yukicoder No.23 - 技の選択

Source

ニコニコミュニティ
問題文

問題概要

敵のHPの初期値は $H$ で,HPが $0$ 以下になると倒したことになる.
普通に攻撃すると必ずダメージを $A$ だけ与えることができる.
必殺技で攻撃すると確率 $2/3$ でダメージを $D$ だけ与えることができ,確率 $1/3$ でミスってダメージを全く与えられない.
敵を倒すまでの攻撃回数の期待値が最小になるように攻撃するとき,その最小値を求める問題.

解法

動的計画法で求める.
状態を敵の残りHP $(=k)$ として,これから敵を倒すまでに必要な攻撃回数の期待値の最小値 $\verb|dp[|k\verb|]|$ を計算する.
必殺技が命中するまでにかかる攻撃回数の期待値は $(2/3)^{-1} = 1.5$ だから
$\quad \verb|dp[|k\verb|]| = \min(\verb|dp[|k-A\verb|]|+1, \verb|dp[|k-D\verb|]|+1.5)$
と計算できる.

C++によるスパゲッティなソースコード

#include<bits/stdc++.h>
using namespace std;

#define REP(i,a,b) for(i=a;i<b;i++)
#define rep(i,n) REP(i,0,n)

#define mygc(c) (c)=getchar_unlocked()
#define mypc(c) putchar_unlocked(c)

void reader(int *x){int k,m=0;*x=0;for(;;){mygc(k);if(k=='-'){m=1;break;}if('0'<=k&&k<='9'){*x=k-'0';break;}}for(;;){mygc(k);if(k<'0'||k>'9')break;*x=(*x)*10+k-'0';}if(m)(*x)=-(*x);}
void reader(int *x, int *y, int *z){reader(x);reader(y);reader(z);}

int H, A, D;
double res[100000];

int main(){
  int i, j, k;

  reader(&H,&A,&D);
  res[0] = 0;
  REP(i,1,H+1){
    res[i] = min(1.0 + (i-A>=0?res[i-A]:0), 1.5 + (i-D>=0?res[i-D]:0));
  }

  printf("%.1f\n",res[H]);

  return 0;
}

Current time: 2017年09月25日07時52分51秒
Last modified: 2014年11月18日03時06分17秒 (by laycrs)
Tags: Competitive_Programming yukicoder
トップページに戻る

Logged in as: unknown user (not login)

ログイン: