区间DP
来源:互联网 发布:mac电子相册制作软件 编辑:程序博客网 时间:2024/05/23 15:39
区间dp
一、题目链接
Description
We give the following inductive definition of a “regular brackets” sequence:
- the empty sequence is a regular brackets sequence,
- if s is a regular brackets sequence, then (s) and [s] are regular brackets sequences, and
- if a and b are regular brackets sequences, then ab is a regular brackets sequence.
- no other sequence is a regular brackets sequence
For instance, all of the following character sequences are regular brackets sequences:
(), [], (()), ()[], ()[()]
while the following character sequences are not:
(, ], )(, ([)], ([(]
Given a brackets sequence of characters a1a2 … an, your goal is to find the length of the longest regular brackets sequence that is a subsequence of s. That is, you wish to find the largest m such that for indices i1, i2, …, imwhere 1 ≤ i1 < i2 < … < im ≤ n, ai1ai2 … aim is a regular brackets sequence.
Given the initial sequence ([([]])]
, the longest regular brackets subsequence is [([])]
.
Input
The input test file will contain multiple test cases. Each input test case consists of a single line containing only the characters (
, )
, [
, and ]
; each input test will have length between 1 and 100, inclusive. The end-of-file is marked by a line containing the word “end” and should not be processed.
Output
For each input case, the program should print the length of the longest possible regular brackets subsequence on a single line.
Sample Input
((()))()()()([]]))[)(([][][)end
Sample Output
66406
Source
题意:求匹配括号的个数。
题解:
三步骤:1.写判断满足题意的函数;2.数据初始化;3.区间dp的更新。
关于dp更新:1.[ i,j ]的区间中,设j为新加入的点,若 i,j 匹配,则dp[i][j]=dp[i+1][j-1]+2. 除此之外,还有持续地下一步更新,把区间以k+1分为两段,设k+1与j匹配,则有dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]);
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- #include<cmath>
- #include<queue>
- #include<cstdlib>
- #include<string>
- using namespace std;
- #define N 110
- char str[N];
- int dp[N][N];
- bool check(int i,int j)
- {
- if(str[i]=='['&&str[j]==']') return true;
- if(str[i]=='('&&str[j]==')') return true;
- return false;
- }
- int main()
- {
- while(~scanf("%s",str))
- {
- if(str[0]=='e')
- break;
- memset(dp,0,sizeof(dp));
- int l=strlen(str);
- for(int i=0;i<l-1;i++)
- if(check(i,i+1)) dp[i][i+1]=2;
- for(int n=3;n<=l;n++)
- {
- for(int i=0; i+n-1<l; i++)
- {
- if(check(i,i+n-1)) dp[i][i+n-1]=dp[i+1][i+n-2]+2;
- for(int j=i;j<i+n-1;j++)
- dp[i][i+n-1]=max(dp[i][i+n-1],dp[i][j]+dp[j+1][i+n-1]);
- }
- }
- printf("%d\n",dp[0][l-1]);
- }
- return 0;
- }
二、记忆化搜索的方法。
整合在一起的代码是 d[i][j]=max(d[i+1]d[j],d[i+1][k-1]+d[k+1][j]+2); i<k<=j; i和k匹配取后者,否之前者。
注意:不匹配的时候注意记得更新 d[i][j]=solve(i+1,j);
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- #include<cmath>
- #include<queue>
- #include<cstdlib>
- #include<string>
- using namespace std;
- #define N 110
- char str[N];
- int dp[N][N];
- bool check(int i,int j)
- {
- if(str[i]=='['&&str[j]==']') return true;
- if(str[i]=='('&&str[j]==')') return true;
- return false;
- }
- int solve(int i,int j)
- {
- if(dp[i][j]>=0) return dp[i][j];
- if(j<=i) return dp[i][j]=0;
- if(j==i+1)
- {
- if(check(i,j))
- return dp[i][j]=2;
- else
- return dp[i][j]=0;
- }
- dp[i][j]=solve(i+1,j); //不满足匹配的条件时的值。
- for(int k=i+1;k<=j;k++)
- {
- if(check(i,k))
- dp[i][j]=max(dp[i][j],solve(i+1,k-1)+solve(k+1,j)+2);
- }
- return dp[i][j];
- }
- int main()
- {
- while(~scanf("%s",str))
- {
- if(str[0]=='e')
- break;
- memset(dp,-1,sizeof(dp));
- int l=strlen(str);
- printf("%d\n",solve(0,l-1));
- }
- return 0;
- }
二、想看题目?戳我呀
Description
The goal is to take cards in such order as to minimize the total number of scored points.
For example, if cards in the row contain numbers 10 1 50 20 5, player might take a card with 1, then 20 and 50, scoring
If he would take the cards in the opposite order, i.e. 50, then 20, then 1, the score would be
Input
Output
Sample Input
610 1 50 50 20 5
Sample Output
3650
Source
题解:运用区间dp的方法。枚举区间[i,j]中 i+1 到j-1 中的每个值,看最小消费是多少。
dp[i,j]=min(dp[i][j],dp[i][k]+dp[k][j]+num[i]*num[k]*num[j]); i<k<j;
注意初始化,动态规划中的初始化需要特别重视,初始化出现错误,结果就会错。
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- #include<cmath>
- #include<queue>
- #include<cstdlib>
- #include<string>
- using namespace std;
- #define N 105
- #define inf 99999999
- int num[N];
- int dp[N][N];
- int main()
- {
- int n;
- while(~scanf("%d",&n))
- {
- for(int i=1;i<=n;i++)
- scanf("%d",&num[i]);
- for(int i=0;i<=N;i++)
- for(int j=0;j<=N;j++)
- dp[i][j]=inf;
- for(int i=1;i<n;i++)
- {
- dp[i][i+2]=num[i]*num[i+1]*num[i+2];
- dp[i][i]=dp[i][i+1]=0;
- }
- for(int k=4;k<=n;k++)
- {
- for(int i=1;i+k-1<=n;i++)
- {
- for(int j=i+1;j<i+k-1;j++)
- dp[i][i+k-1]=min(dp[i][i+k-1],dp[i][j]+dp[j][i+k-1]+num[i]*num[i+k-1]*num[j]);
- }
- }
- printf("%d\n",dp[1][n]);
- }
- return 0;
- }
三、想看题目?戳我呀
Description
Keeping track of all the cows can be a tricky task so Farmer John has installed a system to automate it. He has installed on each cow an electronic ID tag that the system will read as the cows pass by a scanner. Each ID tag's contents are currently a single string with length M (1 ≤ M ≤ 2,000) characters drawn from an alphabet of N (1 ≤ N ≤ 26) different symbols (namely, the lower-case roman alphabet).
Cows, being the mischievous creatures they are, sometimes try to spoof the system by walking backwards. While a cow whose ID is "abcba" would read the same no matter which direction the she walks, a cow with the ID "abcb" can potentially register as two different IDs ("abcb" and "bcba").
FJ would like to change the cows's ID tags so they read the same no matter which direction the cow walks by. For example, "abcb" can be changed by adding "a" at the end to form "abcba" so that the ID is palindromic (reads the same forwards and backwards). Some other ways to change the ID to be palindromic are include adding the three letters "bcb" to the begining to yield the ID "bcbabcb" or removing the letter "a" to yield the ID "bcb". One can add or remove characters at any location in the string yielding a string longer or shorter than the original string.
Unfortunately as the ID tags are electronic, each character insertion or deletion has a cost (0 ≤ cost ≤ 10,000) which varies depending on exactly which character value to be added or deleted. Given the content of a cow's ID tag and the cost of inserting or deleting each of the alphabet's characters, find the minimum cost to change the ID tag so it satisfies FJ's requirements. An empty ID tag is considered to satisfy the requirements of reading the same forward and backward. Only letters with associated costs can be added to a string.
Input
Line 2: This line contains exactly M characters which constitute the initial ID string
Lines 3..N+2: Each line contains three space-separated entities: a character of the input alphabet and two integers which are respectively the cost of adding and deleting that character.
Output
Sample Input
3 4abcba 1000 1100b 350 700c 200 800
Sample Output
900
Hint
Source
题意:问 让给出的的字符串变为回文串的最小花费是多少
题解:首先有一个小tip,对于增删字母的花费,我们每次只会选择最小的花费,所以增删的费用中,我们只需保存最小的在add[i]。我们设dp[i][j]表示字符串从i到j变为回文串的最小花费。
然后有3种情况:1.s[i]=s[j],dp[i][j]=dp[i+1][j-1];
2.如果dp[i+1][j]是(变为)回文串(的消费),则dp[i][j]=dp[i+1][j]+add[i];
3.如果dp[i][j-1]是(变为)回文串(的消费),则dp[i][j]=dp[i][j-1]+add[j];
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- #include<cmath>
- #include<queue>
- #include<cstdlib>
- #include<string>
- using namespace std;
- #define N 2010
- #define inf 0x3f3f3f3f
- int m,n,ad,de;
- int add[30];
- int s[N];
- int dp[N][N];
- int main()
- {
- while(~scanf("%d%d",&n,&m))
- {
- char ch;
- char c[2];
- memset(s,-1,sizeof(s));
- for(int i=0;i<m;i++)
- {
- cin>>ch;
- s[i]=ch-'a';
- }
- for(int i=0;i<n;i++)
- {
- cin>>c;
- int cc=c[0]-'a';
- cin>>ad>>de;
- add[cc]=min(ad,de);
- }
- memset(dp,0,sizeof(dp));
- for(int k=1;k<m;k++)
- {
- for(int i=0,j=k;j<m;i++,j++)
- {
- dp[i][j]=inf;
- if(s[i]==s[j])
- dp[i][j]=dp[i+1][j-1];
- else
- {
- dp[i][j]=min(dp[i][j-1]+add[s[j]],dp[i][j]);
- dp[i][j]=min(dp[i+1][j]+add[s[i]],dp[i][j]);
- }
- }
- }
- printf("%d\n",dp[0][m-1]);
- }
- return 0;
- }
四、瞅啥呢?原题目链接在这里
Description
1. Empty sequence is a regular sequence.
2. If S is a regular sequence, then (S) and [S] are both regular sequences.
3. If A and B are regular sequences, then AB is a regular sequence.
For example, all of the following sequences of characters are regular brackets sequences:
(), [], (()), ([]), ()[], ()[()]
And all of the following character sequences are not:
(, [, ), )(, ([)], ([(]
Some sequence of characters '(', ')', '[', and ']' is given. You are to find the shortest possible regular brackets sequence, that contains the given character sequence as a subsequence. Here, a string a1 a2 ... an is called a subsequence of the string b1 b2 ... bm, if there exist such indices 1 = i1 < i2 < ... < in = m, that aj = bij for all 1 = j = n.
Input
Output
Sample Input
([(]
Sample Output
()[()]
Source
题意:根据题目所给的字符串添加括号,输出最短的匹配括号串。(题目隐含给出的字符串包含空格,所以输入的时候必须用gets输入,scanf 是以回车和空格作为结束符号,gets只以回车作为结束)
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- #include<cmath>
- #include<queue>
- #include<cstdlib>
- #include<string>
- using namespace std;
- #define N 2010
- #define inf 99999999
- struct node
- {
- int t;
- string s;
- }dp[110][110];
- char str[110];
- string ss;
- void init(int l)
- {
- for(int i=0; i<l; i++)
- {
- for(int j=i; j<l; j++)
- {
- dp[i][j].s="";
- dp[i][j].t=inf;
- }
- }
- for(int i=0; i<l; i++)
- {
- dp[i][i].t=1;
- if(ss[i]=='('||ss[i]==')')
- dp[i][i].s="()";
- else
- dp[i][i].s="[]";
- }
- }
- int main()
- {
- while(gets(str))
- {
- ss=str;
- int l=ss.size();
- init(l);
- for(int i=l-1; i>=0; i--)
- {
- for(int j=i+1; j<l; j++)
- {
- if((ss[i]=='('&&ss[j]==')')||(ss[i]=='['&&ss[j]==']'))
- {
- if(dp[i][j].t > dp[i+1][j-1].t)
- {
- dp[i][j].t=dp[i+1][j-1].t;
- dp[i][j].s=ss[i]+dp[i+1][j-1].s+ss[j];
- }
- }
- for(int k=i; k<j; k++)
- {
- if(dp[i][j].t > dp[i][k].t+dp[k+1][j].t)
- {
- dp[i][j].t=dp[i][k].t+dp[k+1][j].t;
- dp[i][j].s=dp[i][k].s+dp[k+1][j].s;
- }
- }
- }
- }
- cout<<dp[0][l-1].s<<endl;
- }
- return 0;
- }
Description
The cows are trying to become better athletes, so Bessie is running on a track for exactly N (1 ≤ N ≤ 10,000) minutes. During each minute, she can choose to either run or rest for the whole minute.
The ultimate distance Bessie runs, though, depends on her 'exhaustion factor', which starts at 0. When she chooses to run in minute i, she will run exactly a distance of Di (1 ≤ Di ≤ 1,000) and her exhaustion factor will increase by 1 -- but must never be allowed to exceed M (1 ≤ M ≤ 500). If she chooses to rest, her exhaustion factor will decrease by 1 for each minute she rests. She cannot commence running again until her exhaustion factor reaches 0. At that point, she can choose to run or rest.
At the end of the N minute workout, Bessie's exaustion factor must be exactly 0, or she will not have enough energy left for the rest of the day.
Find the maximal distance Bessie can run.
Input
* Line 1: Two space-separated integers: N and M
* Lines 2..N+1: Line i+1 contains the single integer: Di
Output
* Line 1: A single integer representing the largest distance Bessie can run while satisfying the conditions.
Sample Input
5 2534210
Sample Output
9
Source
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- #include<cmath>
- #include<queue>
- #include<cstdlib>
- #include<string>
- using namespace std;
- #define N 2010
- #define inf 99999999
- int dp[10005][505];
- int num[10005];
- int main()
- {
- int n,m;
- while(~scanf("%d%d",&n,&m))
- {
- for(int i=1; i<=n; i++)
- {
- scanf("%d",&num[i]);
- }
- memset(dp,0,sizeof(dp));
- for(int i=1; i<=n; i++)
- {
- for(int j=1; j<=m; j++) //初始化取值,任意时间任意疲劳数的初值,方便后面的调用。
- {
- dp[i][j]=dp[i-1][j-1]+num[i];
- }
- dp[i][0]=dp[i-1][0]; //两种情况的判定,疲劳数变为0的情况。
- for(int k=1; k<=m; k++)
- {
- if(i-k>0)
- dp[i][0]=max(dp[i][0],dp[i-k][k]); //保证最后的疲劳数为0的情况下,获得最大的值。
- }
- }
- printf("%d\n",dp[n][0]);
- }
- return 0;
- }
- 区间DP
- 区间DP
- 区间DP
- 区间DP
- ##区间dp##
- 区间dp
- 区间DP
- 区间dp
- 区间dp
- 区间dp
- 区间dp
- 区间dp
- 区间dp
- 区间dp
- 区间DP
- 区间DP
- 区间DP
- 区间dp
- 贝塞尔曲线
- spark机器学习电影推荐
- (五)Spring Bean配置之Bean作用域及生命周期
- tomcat修改控制台日志输出到文件的解决办法__http://wenku.baidu.com/link?url=inKWTkePOVaNcN9o07BGiiOgHaQefnUAhXfj9Bmn-BX
- ProgressBar的几个方法介绍
- 区间DP
- 快速排序
- JAVA简易WEB服务器(五)
- BitmapDrawable.mutate()
- Gitit Bigger 安装
- C语言头文件避免重复包含、#pragma once和#ifndef的区别
- 【转载】mysql数据库中命令行下常用命令的操作(增、删、改、查)和数据类型
- hdu 3001 Travelling 状压dp TSP变形
- JavaScript的事件代理