1. 程式人生 > >City Destruction Kattis - city dp

City Destruction Kattis - city dp

ring scanf ref http set span def %d ora

/**
題目:City Destruction Kattis - city
鏈接:https://vjudge.net/problem/Kattis-city
題意:有n個怪獸,排成一行。每個怪獸有一個生命值和一個爆炸值。每次可以選擇一個怪獸攻擊早造成d傷害。
如果生命值<=0;那麽怪獸i死亡並且爆炸。i+1,i-1第怪獸都會受到
第i個怪獸的爆炸值傷害。如果第i-1被第i炸死,第i-1怪獸不會繼續炸別人。
不會傳遞。也就是只有攻擊者攻擊致死的怪獸才會對i-1,i+1造成爆炸值傷害。
求最少攻擊多少次才能殺死所有的怪獸。
思路:
定義dp[i][j]表示前i個怪獸,j=0表示i-1比i先死,j=1表示i-1比i後死需要的最少攻擊次數。
///本題直接寫遞推方程我寫不出來,因為i和i-1以及未知的i+1都有關聯。i+1是未知的。
所以不好表示,本人菜雞。如果dfs記憶化做法,倒是清晰。

*/ #include <cstdio> #include <cstring> #include <algorithm> #include <set> #include <queue> #include <iostream> #include <vector> using namespace std; #define ms(x,y) memset(x,y,sizeof x) typedef long long LL; const int N = 1e4; const LL INF = 1e18; LL dp[N][
2];///j=0表示i-1比i先死,j=1表示i-1比i晚死。 int h[N], e[N]; int n, d; LL cal(LL r) { if(r<=0) return 0; if(r%d==0){ return r/d; } return r/d+1; } LL dfs(int i,int j) { if(i==n){ return 0; } LL &res = dp[i][j]; if(res!=-1) return res; res = INF; LL r = h[i];
if(j==0){ r -= e[i-1]; res = min(res,dfs(i+1,0)+cal(r)); if(i<n-1){ res = min(res,dfs(i+1,1)+cal(r-e[i+1])); } }else { res = min(res,dfs(i+1,0)+cal(r)); if(i<n-1){ res = min(res,dfs(i+1,1)+cal(r-e[i+1])); } } return res; } int main() { int T; cin>>T; while(T--) { scanf("%d%d",&n,&d); for(int i = 0; i < n; i++){ scanf("%d",&h[i]); } for(int i = 0; i < n; i++){ scanf("%d",&e[i]); } memset(dp, -1, sizeof dp); printf("%lld\n",dfs(0,1)); } return 0; }

City Destruction Kattis - city dp