|
@@ -42,36 +42,11 @@ func nextDebuffCnt() int {
|
|
|
return int(math.Ceil(float64(ak-minAk) / float64(d)))
|
|
|
}
|
|
|
|
|
|
-func simD(debuffCnt, t int, c bool) int {
|
|
|
- if debuffCnt == 0 {
|
|
|
- return t
|
|
|
+func getAttackCnt(st state) int {
|
|
|
+ if st.ak == 0 {
|
|
|
+ return maxInt(1, st.hk/st.ad)
|
|
|
}
|
|
|
- if hp <= ak-d { // Need cure
|
|
|
- if c { // Cured?
|
|
|
- return 0 // Die
|
|
|
- }
|
|
|
- hp = hd - ak
|
|
|
- return simD(debuffCnt, t+1, true) // Cure
|
|
|
- }
|
|
|
- ak = maxInt(0, ak-d)
|
|
|
- hp -= ak
|
|
|
- return simD(debuffCnt-1, t+1, false) // Debuff
|
|
|
-}
|
|
|
-
|
|
|
-func simBA(buffCnt int, st state) int { // Simulate buff and attack
|
|
|
- if st.hk <= 0 { // Kill
|
|
|
- return st.t
|
|
|
- }
|
|
|
- if st.hd <= st.ak && st.ad < st.hk { // Need cure
|
|
|
- if st.c { // Cured?
|
|
|
- return 0 // Die
|
|
|
- }
|
|
|
- return simBA(buffCnt, state{hd - st.ak, st.ad, st.hk, st.ak, st.t + 1, true}) // Cure
|
|
|
- }
|
|
|
- if buffCnt != 0 {
|
|
|
- return simBA(buffCnt-1, state{st.hd - st.ak, st.ad + b, st.hk, st.ak, st.t + 1, false}) // Buff
|
|
|
- }
|
|
|
- return simBA(0, state{st.hd - st.ak, st.ad, st.hk - st.ad, st.ak, st.t + 1, false}) // Attack
|
|
|
+ return maxInt(1, minInt(st.hd/st.ak-1, st.hk/st.ad))
|
|
|
}
|
|
|
|
|
|
func main() {
|
|
@@ -84,16 +59,61 @@ func main() {
|
|
|
println("Case", tc)
|
|
|
|
|
|
buff := getBuffCnt()
|
|
|
- turn := simBA(buff, state{hp, ad, hk, ak, 0, false})
|
|
|
+ st := state{hp, ad, hk, ak, 0, false}
|
|
|
+ for buffCnt := buff; 0 < st.hk; { // !Kill
|
|
|
+ if st.hd <= st.ak && st.ad < st.hk { // Need cure
|
|
|
+ if st.c { // Cured?
|
|
|
+ st.t = 0
|
|
|
+ break // Die
|
|
|
+ }
|
|
|
+ st = state{hd - st.ak, st.ad, st.hk, st.ak, st.t + 1, true} // Cure
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if buffCnt != 0 {
|
|
|
+ buffCnt--
|
|
|
+ st = state{st.hd - st.ak, st.ad + b, st.hk, st.ak, st.t + 1, false} // Buff
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ t := getAttackCnt(st)
|
|
|
+ st = state{st.hd - st.ak*t, st.ad, st.hk - st.ad*t, st.ak, st.t + t, false} // Attack
|
|
|
+ }
|
|
|
+ turn := st.t
|
|
|
debuff, dt := nextDebuffCnt(), 0
|
|
|
+ sim:
|
|
|
for debuff != 0 {
|
|
|
- dt = simD(debuff, dt, false)
|
|
|
- if dt == 0 {
|
|
|
- break
|
|
|
- }
|
|
|
- dbat := simBA(buff, state{hp, ad, hk, ak, dt, false})
|
|
|
- if turn == 0 || dbat < turn {
|
|
|
- turn = dbat
|
|
|
+ c := false
|
|
|
+ for debuff != 0 {
|
|
|
+ if hp <= ak-d { // Need cure
|
|
|
+ if c { // Cured?
|
|
|
+ break sim // Die
|
|
|
+ }
|
|
|
+ hp, dt, c = hd-ak, dt+1, true
|
|
|
+ continue // Cure
|
|
|
+ }
|
|
|
+ ak = maxInt(0, ak-d)
|
|
|
+ debuff, hp, dt, c = debuff-1, hp-ak, dt+1, false // Debuff
|
|
|
+ } // Simulate debuff
|
|
|
+ println("sim debuff", dt)
|
|
|
+ st = state{hp, ad, hk, ak, dt, false}
|
|
|
+ for buffCnt := buff; 0 < st.hk; { // !Kill
|
|
|
+ if st.hd <= st.ak && st.ad < st.hk { // Need cure
|
|
|
+ if st.c { // Cured?
|
|
|
+ st.t = 0
|
|
|
+ break // Die
|
|
|
+ }
|
|
|
+ st = state{hd - st.ak, st.ad, st.hk, st.ak, st.t + 1, true} // Cure
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if buffCnt != 0 {
|
|
|
+ buffCnt--
|
|
|
+ st = state{st.hd - st.ak, st.ad + b, st.hk, st.ak, st.t + 1, false} // Buff
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ t := getAttackCnt(st)
|
|
|
+ st = state{st.hd - st.ak*t, st.ad, st.hk - st.ad*t, st.ak, st.t + t, false} // Attack
|
|
|
+ } // Simulate buff and attack
|
|
|
+ if turn == 0 || st.t < turn {
|
|
|
+ turn = st.t
|
|
|
}
|
|
|
debuff = nextDebuffCnt()
|
|
|
}
|
|
@@ -112,3 +132,10 @@ func maxInt(x, y int) int {
|
|
|
}
|
|
|
return x
|
|
|
}
|
|
|
+
|
|
|
+func minInt(x, y int) int {
|
|
|
+ if x < y {
|
|
|
+ return x
|
|
|
+ }
|
|
|
+ return y
|
|
|
+}
|