Problem
有n条狼排成一排,每杀掉一个狼会受到 a [ i ] a[i] a[i] 的伤害,同时,每个狼可以为与其相邻的狼增加 b [ i ] b[i] b[i] 点伤害。杀掉一个狼,其余的狼自动填补空位。问:杀死所有的狼受到的最小伤害。
Solution
区间合并:杀掉第k个狼后,其两侧的区间就合并了。
状态转移方程:
d
p
[
l
]
[
r
]
=
d
p
[
l
]
[
k
−
1
]
+
d
p
[
k
+
1
]
[
r
]
+
a
[
k
]
+
b
[
l
−
1
]
+
b
[
r
+
1
]
dp[l][r] = dp[l][k - 1] + dp[k + 1][r] + a[k] + b[l - 1] + b[r + 1]
dp[l][r]=dp[l][k−1]+dp[k+1][r]+a[k]+b[l−1]+b[r+1]
Code
const int N = 2e2 + 5, M = 1e6 + 7;
ll a[N], b[N], f[N][N];
int main()
{
IOS;
int T, cas = 0; cin >> T;
while (T--)
{
int n; cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n; i++)
cin >> b[i];
b[0] = b[n + 1] = 0;
for (int i = 1; i <= n; i++)
f[i][i] = b[i - 1] + b[i + 1] + a[i];
for(int len = 2; len <= n; len++)
for (int l = 1; l <= n - len + 1; l++)
{
int r = l + len - 1;
f[l][r] = inf;
for (int k = l; k <= r; k++)
f[l][r] = min(f[l][r], f[l][k - 1] + f[k + 1][r] + a[k] + b[l - 1] + b[r + 1]);
}
cout << "Case #" << ++cas << ": ";
cout << f[1][n] << endl;
}
return 0;
}
Rethinking
关键是如何对区间进行合并,比赛时没有想出来怎么合并,一直在写贪心的写法。浪费掉大量的时间,最后一直消磨时间,也没有继续坐下去的耐心了。