渐渐认识到区域赛更侧重的是思维及基本算法的灵活运用,而不是算法的量(仅个人见解),接下来要更多侧重思维训练了。
区间DP,dp[i][j]表示从i到j最终剩余第i 与第j只的最小伤害值,设置0与n+1两个虚拟的狼,状态转移方程如下:
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j] + b[i] + b[j])
#include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<vector> #include<cmath> #include<utility> using namespace std; typedef long long LL; const int N = 208, INF = 0x3F3F3F3F; #define MS(a, num) memset(a, num, sizeof(a)) #define PB(A) push_back(A) #define FOR(i, n) for(int i = 0; i < n; i++) int a[N], b[N]; int dp[N][N]; int main(){ int t; cin>>t; for(int cas = 1; cas <= t; cas++){ int n; scanf("%d", &n); int sum = 0; for(int i = 1; i <= n; i++){ scanf("%d", &a[i]); sum += a[i]; } for(int i = 1; i <= n; i++){ scanf("%d", &b[i]); } b[n + 1] = b[0] = 0; memset(dp, 0x3F, sizeof(dp)); for(int i = 0 ; i <= n + 1; i++){ dp[i][i] = 0; dp[i][i + 1] = 0; } for(int len = 3;len <= n + 2; len++){ for(int i = 0, j = len - 1; j <= n + 1; i++, j++){ for(int k = i + 1; k < j; k++){ dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j] + b[i] + b[j]); } } } printf("Case #%d: %d ", cas, dp[0][n + 1] + sum); } return 0; }