Dire Wolf HDU - 5115
一开始很自然的想到了贪心,跑了一下贪心,发现无法处理某一段已经被选走的情况,根据数据范围,区间dp比较适合,能储存区间取样信息
设dp[i][j]为已经杀死区间[i,j]的最小值,可以得到转移方程,dp[i][j] = min(dp[i][k-1]+dp[k+1][j]+a[k]+b[i-1]+b[j+1]),也就是说选用k为中间点,合并i-(k-1),(k+1)-j两个区间,且这两个区间已经被选走,能产生的影响为这两个区间的另一侧,注意初始化将非法区域设为0
#include<bits/stdc++.h> using namespace std; #define lowbit(x) ((x)&(-x)) typedef long long LL; typedef pair<int,int> pii; int a[203], b[203], dp[203][203]; void run_case() { int n; cin >> n; memset(dp, 0, sizeof(dp)); for(int i = 1; i <= n; ++i) cin >> a[i]; for(int i = 1; i <= n; ++i) cin >> b[i]; a[0] = a[n+1] = b[0] = b[n+1] = 0; for(int i = 1; i <= n; ++i) for(int j = i+1; j <= n; ++j) dp[i][j] = 0x3f3f3f3f; for(int i = 1; i <= n; ++i) dp[i][i] = a[i] + b[i-1] + b[i+1]; for(int i = n-1; i >= 1; --i) { for(int j = i+1; j <= n; ++j) { for(int k = i; k <= j; ++k) { dp[i][j] = min(dp[i][j], dp[i][k-1]+dp[k+1][j]+a[k]+b[i-1]+b[j+1]); } } } cout << dp[1][n] << "\n"; } int main() { ios::sync_with_stdio(false), cin.tie(0); cout.flags(ios::fixed);cout.precision(10); int t; cin >> t; for(int i = 1; i <= t; ++i) { cout << "Case #" << i << ": "; run_case(); } //cout.flush(); return 0; }