HDU-3506 二维四边形不等式

Monkey Party

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 2665    Accepted Submission(s): 1074

Problem Description

Far away from our world, there is a banana forest. And many lovely monkeys live there. One day, SDH(Song Da Hou), who is the king of banana forest, decides to hold a big party to celebrate Crazy Bananas Day. But the little monkeys don‘t know each other, so as the king, SDH must do something. 
Now there are n monkeys sitting in a circle, and each monkey has a making friends time. Also, each monkey has two neighbor. SDH wants to introduce them to each other, and the rules are: 
1.every time, he can only introduce one monkey and one of this monkey‘s neighbor. 
2.if he introduce A and B, then every monkey A already knows will know every monkey B already knows, and the total time for this introducing is the sum of the making friends time of all the monkeys A and B already knows; 
3.each little monkey knows himself; 
In order to begin the party and eat bananas as soon as possible, SDH want to know the mininal time he needs on introducing.

Input

There is several test cases. In each case, the first line is n(1 ≤ n ≤ 1000), which is the number of monkeys. The next line contains n positive integers(less than 1000), means the making friends time(in order, the first one and the last one are neighbors). The input is end of file.

Output

For each case, you should print a line giving the mininal time SDH needs on introducing.

Sample Input

8
5 2 4 7 6 1 3 9

Sample Output

105

Author

PerfectCai

Source

2010 ACM-ICPC Multi-University Training Contest(7)——Host by HIT

二维四边形不等式:

定理一:

如果dp[i][j] = Min(dp[i][k] + dp[k + 1][j] + w(i, j)), 若

(1)w满足四边形不等式

(2)对于a < b < c < d,满足w(a, d) > w(b, c)

则dp满足四边形不等式

定理二:

若dp满足四边形不等式,设p[i][j]为dp[i][j]转移来的k

则p[i][j - 1] <= p[i][j] <= p[i + 1][j];

具体操作:

在转移时只需讲k由p[i][j - 1]枚举至p[i + 1][j]即可。可以证明,时间复杂度n2.

感觉比一维四边形不等式好写的多...

 1 #include <iostream>
 2 #include <fstream>
 3 #include <sstream>
 4 #include <cstdlib>
 5 #include <cstdio>
 6 #include <cmath>
 7 #include <string>
 8 #include <cstring>
 9 #include <algorithm>
10 #include <queue>
11 #include <stack>
12 #include <vector>
13 #include <set>
14 #include <map>
15 #include <list>
16 #include <iomanip>
17 #include <cctype>
18 #include <cassert>
19 #include <bitset>
20 #include <ctime>
21
22 using namespace std;
23
24 #define pau system("pause")
25 #define ll long long
26 #define pii pair<int, int>
27 #define pb push_back
28 #define mp make_pair
29 #define mp make_pair
30 #define pli pair<ll, int>
31 #define clr(a, x) memset(a, x, sizeof(a)
32
33 const double pi = acos(-1.0);
34 const int INF = 0x3f3f3f3f;
35 const int MOD = 1e9 + 7;
36 const double EPS = 1e-9;
37
38 /*
39 #include <ext/pb_ds/assoc_container.hpp>
40 #include <ext/pb_ds/tree_policy.hpp>
41 using namespace __gnu_pbds;
42 #define TREE tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update>
43 TREE T;
44 */
45
46 int n, a[2015], dp[2015][2015], p[2015][2015], sum[2015];
47 int main() {
48     while (~scanf("%d", &n)) {
49         for (int i = 1; i <= n; ++i) {
50             scanf("%d", &a[i]);
51             a[i + n] = a[i];
52         }
53         for (int i = 1; i <= n << 1; ++i) {
54                 sum[i] = sum[i - 1] + a[i];
55         }
56         for (int i = 1; i <= n << 1; ++i) {
57                 p[i][i] = i;
58                 dp[i][i] = 0;
59         }
60         for (int l = 2; l <= n; ++l) {
61                 for (int i = 1; i <= 2 * n - l + 1; ++i) {
62                         int j = i + l - 1;
63                         dp[i][j] = INF;
64                         for (int k = p[i][j - 1]; k <= p[i + 1][j]; ++k) {
65                                 if (dp[i][k] + dp[k + 1][j] < dp[i][j]) {
66                                         dp[i][j] = dp[i][k] + dp[k + 1][j];
67                                         p[i][j] = k;
68                                 }
69                         }
70                         dp[i][j] += sum[j] - sum[i - 1];
71                 }
72         }
73         int ans = INF;
74         for (int i = 1; i <= n; ++i) {
75                 ans = min(ans, dp[i][i + n - 1]);
76         }
77         printf("%d\n", ans);
78     }
79     return 0;
80 }

原文地址:https://www.cnblogs.com/BIGTOM/p/9694562.html

时间: 2025-01-06 21:21:36

HDU-3506 二维四边形不等式的相关文章

HDU 2069二维母函数

显然母函数,有一个地方需要注意.当输入0时,只有一种方法,所以输出1. 代码: 1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #include <iostream> 5 using namespace std; 6 int c1[255][111], c2[255][111]; 7 main() 8 { 9 10 int n, i, j, k, l; 11 int a[

HDU 2159FATE(二维背包)

题目地址:HDU 2159 二维的背包,刚开始用的一维,老感觉哪里不对,有两个制约因素.于是就改成了二维的,就过了.. 代码如下: #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <cmath> #include <sta

HDU 1823 二维线段树(区间max)

Luck and Love Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5262    Accepted Submission(s): 1317 Problem Description 世界上上最远的距离不是相隔天涯海角而是我在你面前可你却不知道我爱你                ―― 张小娴 前段日子,枫冰叶子给Wiskey做了

HDU 1892 二维树状数组

See you~ Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 3485    Accepted Submission(s): 1103 Problem Description Now I am leaving hust acm. In the past two and half years, I learned so many kno

hdu 4819 二维线段树模板

/* HDU 4819 Mosaic 题意:查询某个矩形内的最大最小值, 修改矩形内某点的值为该矩形(Mi+MA)/2; 二维线段树模板: 区间最值,单点更新. */ #include<bits/stdc++.h> using namespace std; const int INF = 0x3f3f3f3f; const int MAXN = 1010; int N, Q; struct Nodey { int l, r; int Max, Min; }; int locx[MAXN], l

HDU 3496 (二维费用的01背包) Watch The Movie

多多想看N个动画片,她对这些动画片有不同喜欢程度,而且播放时长也不同 她的舅舅只能给她买其中M个(不多不少恰好M个),问在限定时间内观看动画片,她能得到的最大价值是多少 如果她不能在限定时间内看完买回来的动画片,则输出0 这里借用大牛的背包九讲的讲义,讲的很清楚 问题 二维费用的背包问题是指:对于每件物品,具有两种不同的费用:选择这件物品必须同时付出这两种代价:对于每种代价都有一个可付出的最大值(背包容量).问怎样选择物品可以得到最大的价值.设这两种代价分别为代价1和代价2,第i件物品所需的两种

HDU 1823 二维线段树

二维线段树入门题 分别以身高和活泼度开两维 以身高-100,活泼度*10,为两个区间 所谓的二维就是在第一维查找到正确位置时,进入第二维再查找 #include "stdio.h" #include "string.h" double ans; double Max(double a,double b) { if (a<b) return b;else return a; } struct Mark { int l,r; double x; }; struct

hdu 3496 二维费用的01背包

算是比较简单的二维费用背包了吧,注意在某一维上要求“装满”. 另外:对于多维费用的背包,最内层的循环可以逆着写,想一想,为什么. 1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 using namespace std; 6 7 const int INF = -99999999; 8 const int N = 101; 9 con

hdu 2159 二维完全背包

背景:二维数组为限制条件的完全背包,1Y. 思路:转移方程:F[i][j]=max{F[i][j],F[i-1][j-C[k]+W[k]},F[i][j]为在i为最大人数为i,最大忍耐度为j的情况下所能达到的最大经验值.一旦经验值达到目标要求经验值,就记录当前罪恶值,找出所有大到经验要求罪恶值中的最小罪恶值即可. 学习:进化仍然是转移方程的确立,背包类问题,按照模型进行变换就好.找到限制条件和物品选择,对限制条件进行拆分为每种可能的离散块. 我的代码: #include<cstdio> #in