动态规划——区间

Wikioi 1048 石子归并

题目描述 Description

有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量和w[i]+w[i+1]。问安排怎样的合并顺序,能够使得总合并代价达到最小。

输入描述 Input Description

第一行一个整数n(n<=100)

第二行n个整数w1,w2...wn  (wi <= 100)

输出描述 Output Description

一个整数表示最小合并代价

样例输入 Sample Input

4

4 1 1 4

样例输出 Sample Output

18

思路:

以区间长度划分阶段

ps.如果是任意两堆直接贪心,越是先合并的计算次数就越多

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 #include<cstring>
 5 #include<algorithm>
 6
 7 using namespace std;
 8 const int maxn = 200,maxnum = 10000000;
 9 int n,j,value[maxn],sum[maxn],dp[maxn][maxn];
10 int main(){
11     cin>>n;
12     for(int i = 1;i <= n;i++){
13         cin>>value[i];
14         sum[i]= sum[i-1] + value[i];
15     }
16     for(int l = 2;l <= n;l++){
17         for(int i = 1;i <= n - l + 1;i++){
18             j = i + l - 1;
19             dp[i][j] = maxnum;
20             for(int k = i;k < j;k++)
21                dp[i][j] = min(dp[i][j],dp[i][k] + dp[k+1][j] + sum[j] - sum[i-1]);
22         }
23     }
24     cout<<dp[1][n];
25     return 0;
26 }

Wikioi 3002 石子归并3

题目描述 Description

有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量和w[i]+w[i+1]。问安排怎样的合并顺序,能够使得总合并代价达到最小。

输入描述 Input Description

第一行一个整数n(n<=3000)

第二行n个整数w1,w2...wn  (wi <= 3000)

输出描述 Output Description

一个整数表示最小合并代价

样例输入 Sample Input

4

4 1 1 4

样例输出 Sample Output

18

数据范围及提示 Data Size & Hint

数据范围相比“石子归并” 扩大了

思路:

四边形不等式,记录区间划分点K

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 #include<cstring>
 5 #include<algorithm>
 6
 7 using namespace std;
 8 const int maxn = 4000,maxnum = 100000000;
 9 int n,j,value[maxn],sum[maxn],dp[maxn][maxn],a[maxn][maxn];
10 int main(){
11     cin>>n;
12     for(int i = 1;i <= n;i++){
13         cin>>value[i];
14         sum[i]= sum[i-1] + value[i];
15         a[i][i] = i;
16     }
17     for(int l = 2;l <= n;l++){
18         for(int i = 1;i <= n - l + 1;i++){
19             j = i + l - 1;
20             dp[i][j] = maxnum;
21             for(int k = a[i][j-1];k <= a[i+1][j];k++){
22                 if(dp[i][j] > dp[i][k] + dp[k+1][j] + sum[j] - sum[i-1]){
23                     dp[i][j] = dp[i][k] + dp[k+1][j] + sum[j] - sum[i-1];
24                     a[i][j] = k;
25                 }
26
27             }
28
29         }
30     }
31     cout<<dp[1][n];
32     return 0;
33 }

Wikioi 2102 石子归并2

题目描述 Description

在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。
试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.

输入描述 Input Description

数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.

输出描述 Output Description

输出共2行,第1行为最小得分,第2行为最大得分.

样例输入 Sample Input

4
4 4 5 9

样例输出 Sample Output

43
54

数据范围及提示 Data Size & Hint

经典的区间动态规划。

思路:

求最小值的过程与求最大值的过程基本一样

Wikioi 3657 括号序列

题目描述 Description

我们用以下规则定义一个合法的括号序列:

(1)空序列是合法的

(2)假如S是一个合法的序列,则 (S) 和[S]都是合法的

(3)假如A 和 B 都是合法的,那么AB和BA也是合法的

例如以下是合法的括号序列:

()[](())([])()[]()[()]

以下是不合法括号序列的:

([])(([])([()

现在给定一些由‘(‘, ‘)‘, ‘[‘, ,‘]‘构成的序列 ,请添加尽量少的括号,得到一个合法的括号序列。

输入描述 Input Description

输入包括号序列S。含最多100个字符(四种字符: ‘(‘, ‘)‘, ‘[‘ and ‘]‘) ,都放在一行,中间没有其他多余字符。

输出描述 Output Description

使括号序列S成为合法序列需要添加最少的括号数量。

样例输入 Sample Input

([()

样例输出 Sample Output

2

数据范围及提示 Data Size & Hint

【样例说明】
最少添加2个括号可以得到合法的序列:()[()]或([()])
【数据范围】
S的长度<=100 (最多100个字符)。

思路:

长度划分,状态左右端点,dp[i][j] = dp[i+1][j-1] + 1(if i matches to j)

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 #include<cstring>
 5 #include<algorithm>
 6
 7 using namespace std;
 8 const int maxn = 200,maxnum = 20000000;
 9 int n,c,value[maxn],dp[maxn][maxn],sign,j,q;
10 char cmd;
11 string s;
12 int main(){
13     n = c = 0;
14     getline(cin,s);
15     q = s.length();
16     for(int i = 1;i <= q;i++){
17         cmd = s[i-1];
18         if(cmd == ‘(‘) {value[i-c] = 1;n++;}
19         if(cmd == ‘[‘) {value[i-c] = 2;n++;}
20         if(cmd == ‘]‘) {value[i-c] = 3;n++;}
21         if(cmd == ‘)‘) {value[i-c] = 4;n++;}
22     }
23     memset(dp,0,sizeof(dp));
24     for(int i = 1;i <= n;i++) dp[i][i] = 1;
25     for(int l = 2;l <= n;l++){
26         for(int i = 1;i <= n -l + 1;i++){
27             j = i + l - 1;
28             dp[i][j] = maxnum;
29             if(value[i] + value[j] == 5 && value[i] < value[j]) dp[i][j] = dp[i+1][j-1];
30             for(int k = i;k < j;k++){
31                 dp[i][j] = min(dp[i][j],dp[i][k] + dp[k+1][j]);
32             }
33
34         }
35     }
36     cout<<dp[1][n];
37     return 0;
38 }

时间: 2024-10-10 17:33:01

动态规划——区间的相关文章

[hdu contest 2019-07-29] Azshara&#39;s deep sea 计算几何 动态规划 区间dp 凸包 graham扫描法

今天hdu的比赛的第一题,凸包+区间dp. 给出n个点m个圆,n<400,m<100,要求找出凸包然后给凸包上的点连线,连线的两个点不能(在凸包上)相邻,连线不能与圆相交或相切,连线不能相交但是可以有公共端点. 首先找出凸包,然后把n*n条边和m个圆算点到直线距离验证一下边是否与圆相交存到e[n][n]里. 然后显然是一个dp,但是我开始看错题目了以为不能有公共端点,能有公共端点的情况考虑一下像一个找三角形的过程,就是区间dp. 区间dp有一点妙的地方是最大区间范围是凸包点数而不用+1,因为连

Light OJ 1025 - The Specials Menu(动态规划-区间dp)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1025 题目大意:一串字符, 通过删除其中一些字符, 能够使这串字符变成回文串. 现在给你一串字符,问能够得到多少种不同的回文串: 注意:字符串"abba", 可以得到9串回文串,分别为'a', 'a', 'b', 'b', 'aa', 'bb', 'aba', 'aba', 'abba'. 解题思路:声明dp[i][j]为字符串[i,j]区间中通过删除可以得到不同回

O - Treats for the Cows POJ 3186 ( 动态规划+区间 )

O - Treats for the Cows Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit Status Practice POJ 3186 Description FJ has purchased N (1 <= N <= 2000) yummy treats for the cows who get money for giving vast amounts of milk.

动态规划-区间dp-Palindrome Removal

2019-11-09 10:31:09 问题描述: 问题求解: n = 100,典型的O(n ^ 3)的动规问题.一般来说这种O(n ^ 3)的问题可以考虑使用区间dp来解决. 区间dp是典型的三层结构,最外围枚举区间长度,中间层枚举起点,最里层枚举截断点,因此区间dp的时间复杂度往往为O(n ^ 3). public int minimumMoves(int[] arr) { int n = arr.length; int[][] dp = new int[n + 1][n + 1]; for

codevs——2102 石子归并 2(区间DP)

时间限制: 10 s 空间限制: 256000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分.试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分. 输入描述 Input Description 数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数. 输出

codevs——1048 石子归并 (区间DP)

时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量和w[i]+w[i+1].问安排怎样的合并顺序,能够使得总合并代价达到最小. 输入描述 Input Description 第一行一个整数n(n<=100) 第二行n个整数w1,w2...wn  (wi <= 100) 输出描述 Output Descriptio

1154 能量项链[区间dp]

1154 能量项链 2006年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 在Mars星球上,每个Mars人都随身佩带着一串能量项链.在项链上有N颗能量珠.能量珠是一颗有头标记与尾标记的珠子,这些标记对应着某个正整数.并且,对于相邻的两颗珠子,前一颗珠子的尾标记一定等于后一颗珠子的头标记.因为只有这样,通过吸盘(吸盘是Mars人吸收能量的一种器官)的作用,这两颗珠子才能聚合成一颗珠子,同时释放出可

1166 矩阵取数游戏[区间dp+高精度]

1166 矩阵取数游戏 2007年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description [问题描述]帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下:1. 每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素:2. 每次取走的各个元素只能是该元素所在行的行首或行尾:3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分

洛谷P2904 [USACO08MAR]跨河River Crossing 动态规划

洛谷P2904 [USACO08MAR]跨河River Crossing动态规划 区间DP f[ i ] 表示 将 i 头牛 运了过去,然后John 又返回所需要的最少时间 1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <cstdlib> 5 #include <string> 6 #include <algorithm> 7 #inclu