Kaynağa Gözat

Remove iteration to avoid stack overflow (but still cannot pass the large case)

dengxinyi 6 yıl önce
ebeveyn
işleme
05bf858de5
2 değiştirilmiş dosya ile 96 ekleme ve 37 silme
  1. 32 0
      2017/1A/C/C-large-answers.out
  2. 64 37
      2017/1A/C/main.go

+ 32 - 0
2017/1A/C/C-large-answers.out

@@ -5,3 +5,35 @@ Case #4: 5
 Case #5: IMPOSSIBLE
 Case #6: 11
 Case #7: 11459
+Case #8: 1592589947
+Case #9: 1664421834
+Case #10: 42
+Case #11: 13
+Case #12: 844511227
+Case #13: 433822739
+Case #14: 856894040
+Case #15: 1615021050
+Case #16: 1656791128
+Case #17: 5
+Case #18: 1641896288
+Case #19: 1
+Case #20: 1641598580
+Case #21: 186
+Case #22: 1581738041
+Case #23: 31
+Case #24: 1720299879
+Case #25: 1585245707
+Case #26: 565444224
+Case #27: 1702977340
+Case #28: 59
+Case #29: 536967058
+Case #30: 13
+Case #31: 4
+Case #32: 1723997217
+Case #33: 1608890495
+Case #34: 39884
+Case #35: 33802
+Case #36: 19586
+Case #37: 870123129
+Case #38: 12
+Case #39: 27

+ 64 - 37
2017/1A/C/main.go

@@ -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
+}