题意: 给一个n, 第二行给n堆的价值v[i], 第三行给a[i]. a[i]表示把i堆合在一起需要的花费.
求把n堆变成类似回文的 需要的最小花费.
思路:
①记忆化搜索 比较好理解...
dp[l][r] 记录l到r的最小花费
枚举对称轴 维护每次l到r之间对称
dp[l][r]=min(dp[l][r], a[cur-l]+a[r-i]+dfs(cur+1, i-1));
l左边和r右边的合并
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <climits> 5 #include <cctype> 6 #include <cmath> 7 #include <string> 8 #include <sstream> 9 #include <iostream> 10 #include <algorithm> 11 #include <iomanip> 12 using namespace std; 13 #include <queue> 14 #include <stack> 15 #include <vector> 16 #include <deque> 17 #include <set> 18 #include <map> 19 typedef long long LL; 20 typedef long double LD; 21 #define pi acos(-1.0) 22 #define lson l, m, rt<<1 23 #define rson m+1, r, rt<<1|1 24 typedef pair<int, int> PI; 25 typedef pair<int, PI> PP; 26 #ifdef _WIN32 27 #define LLD "%I64d" 28 #else 29 #define LLD "%lld" 30 #endif 31 //#pragma comment(linker, "/STACK:1024000000,1024000000") 32 //LL quick(LL a, LL b){LL ans=1;while(b){if(b & 1)ans*=a;a=a*a;b>>=1;}return ans;} 33 //inline int read(){char ch=' ';int ans=0;while(ch<'0' || ch>'9')ch=getchar();while(ch<='9' && ch>='0'){ans=ans*10+ch-'0';ch=getchar();}return ans;} 34 inline void print(LL x){printf(LLD, x);puts("");} 35 //inline void read(double &x){char c = getchar();while(c < '0') c = getchar();x = c - '0'; c = getchar();while(c >= '0'){x = x * 10 + (c - '0'); c = getchar();}} 36 37 int a[5005]; 38 LL num[5005]; 39 int cost[5005]; 40 int dp[5005][5005]; 41 int dfs(int l, int r) 42 { 43 if(dp[l][r]!=-1) 44 return dp[l][r]; 45 if(l>=r) 46 return dp[l][r]=0; 47 dp[l][r]=cost[r-l]; 48 int cur=l; 49 for(int i=r;i>=l;i--) 50 { 51 for(;cur<i && (num[cur]-num[l-1]<num[r]-num[i-1]);cur++); 52 if(cur==i) 53 break; 54 if(num[cur]-num[l-1]==num[r]-num[i-1]) 55 dp[l][r]=min(dp[l][r], cost[cur-l]+cost[r-i]+dfs(cur+1, i-1)); 56 } 57 return dp[l][r]; 58 } 59 int main() 60 { 61 #ifndef ONLINE_JUDGE 62 freopen("in.txt", "r", stdin); 63 freopen("out.txt", "w", stdout); 64 #endif 65 int n; 66 while(~scanf("%d", &n) && n) 67 { 68 num[0]=0; 69 for(int i=1;i<=n;i++) 70 { 71 scanf("%d", &a[i]); 72 num[i]=num[i-1]+(LL)a[i]; 73 } 74 for(int i=0;i<n;i++) 75 scanf("%d", &cost[i]); 76 for(int i=0;i<=n;i++) 77 fill(dp[i]+i+1, dp[i]+n+1, -1); 78 //memset(dp, -1, sizeof(dp)); 79 printf("%d\n", dfs(1, n)); 80 } 81 return 0; 82 }