cdoj 1131 男神的礼物 区间dp

题目链接

给n个数字, 拿走两个数字a, b会有a*b的代价, 并新生成一个数字(a+b)%100, 求拿走所有数字所需的最小代价。

区间dp, 枚举分界点, 然后记忆化搜索。

 1 #include <iostream>
 2 #include <vector>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <cmath>
 7 #include <map>
 8 #include <set>
 9 #include <string>
10 #include <queue>
11 #include <stack>
12 #include <bitset>
13 using namespace std;
14 #define pb(x) push_back(x)
15 #define ll long long
16 #define mk(x, y) make_pair(x, y)
17 #define lson l, m, rt<<1
18 #define mem(a) memset(a, 0, sizeof(a))
19 #define rson m+1, r, rt<<1|1
20 #define mem1(a) memset(a, -1, sizeof(a))
21 #define mem2(a) memset(a, 0x3f, sizeof(a))
22 #define rep(i, n, a) for(int i = a; i<n; i++)
23 #define fi first
24 #define se second
25 typedef pair<int, int> pll;
26 const double PI = acos(-1.0);
27 const double eps = 1e-8;
28 const int mod = 1e9+7;
29 const int inf = 1061109567;
30 const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
31 int dp[105][105], a[105], sum[105];
32 int dfs(int l, int r) {
33     if(~dp[l][r])
34         return dp[l][r];
35     if(l>=r)
36         return 0;
37     if(r-l==1)
38         return a[l]*a[r];
39     dp[l][r] = inf;
40     for(int i = l; i<=r; i++) {
41         dp[l][r] = min(dp[l][r], ((sum[i]-sum[l-1])%100)*((sum[r]-sum[i])%100)+dfs(l, i)+dfs(i+1, r));
42     }
43     return dp[l][r];
44 }
45 int main()
46 {
47     ios::sync_with_stdio(0);
48     int t, n;
49     cin>>t;
50     while(t--) {
51         cin>>n;
52         mem1(dp);
53         for(int i = 1; i<=n; i++) {
54             cin>>a[i];
55             sum[i] = sum[i-1]+a[i];
56         }
57         int ans = dfs(1, n);
58         cout<<ans<<endl;
59     }
60     return 0;
61 }

 

posted on 2015-12-26 15:42  yohaha  阅读(149)  评论(0编辑  收藏  举报

导航