Description
Input
Output
Sample Input
5
Ab3bd
Sample Output
2
题意: 题目给出一个字符串和它的长度.求添加最小的字符数,使这个字符串成为回文串;
题解: 区间DP, dp[l,r]表示下标l到下标r这部分区间的最优解,则if(s[l] == s[r]) dp[l][r] = dp[l + 1][r- 1]; else dp[l][r] = min(dp[l][r - 1] + 1,dp[l + 1][r] + 1);
这道题要注意要用滚动数组做,因为5000 * 5000 内存爆了;
AC代码:
<span style="font-size:12px;"><span style="font-size:12px;">#include <cstring> #include <cstdio> #include <iostream> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <map> #include <cctype> #define INF 1e5 + 100 using namespace std; typedef long long ll; const int M = 5500; int dp[2][M],n; char s[M]; int main() { scanf("%d %s",&n,s + 1); for(int i = n; i >= 1; i--) { for(int j = i; j <= n; j++) { if(i == j) dp[i % 2][j] = 0; else { if(s[i] == s[j]) { if(i + 1 == j) dp[i % 2][j] = 0; else dp[i % 2][j] = dp[(i + 1) % 2][j - 1]; } else dp[i % 2][j] = min(dp[i % 2][j - 1] + 1,dp[(i + 1) % 2][j] + 1); } } } printf("%d\n",dp[1][n]); return 0; }
Sample Output
6 6 4 0 6 题意: 题目给出一个字符串,求串中存在的最长的匹配串; 题解: (区间DP) 逆向考虑,先求出添加最少的字符使其为匹配串,然后用串的长度去减即可; AC代码:<span style="font-size:12px;">#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int M = 110; char s[M]; int dp[M][M]; bool check(int i,int j) { if(s[i] == '(' && s[j] == ')') return true; if(s[i] == '[' && s[j] == ']') return true; return false; } int main() { //freopen("in","r",stdin); while(~scanf("%s",s + 1)) { int n; if(!strcmp(s + 1,"end")) break; n = strlen(s + 1); memset(dp,0,sizeof(dp)); for(int i = n; i >= 1; i--) { dp[i][i] = 1; for(int j = i + 1; j <= n; j++) { if(check(i,j)) { if(i + 1 == j) dp[i][j] = 0; else dp[i][j] = dp[i + 1][j - 1]; } else dp[i][j] = min(dp[i + 1][j] + 1,dp[i][j - 1] + 1); for(int k = i + 1; k < j - 1; k++) dp[i][j] = min(dp[i][j],dp[i][k] + dp[k + 1][j]); } } printf("%d\n",n - dp[1][n]); } return 0; } </span>
C - Brackets SequenceTime Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u
Description
Let us define a regular brackets sequence in the following way:
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
The input file contains at most 100 brackets (characters '(', ')', '[' and ']') that are situated on a single line without any other characters among them.Output
Write to the output file a single line that contains some regular brackets sequence that has the minimal possible length and contains the given sequence as a subsequence.Sample Input
([(]
Sample Output
()[()] 题意: 括号匹配问题,跟上面的一样,不过需要输出最优解的路径. 题解:区间DP,以dp[i][j]表示i到j这段区间的最优解,然后找出状态. 最后输出路径时只需递归输出,不过这道题目需要注意空串的情况.
AC代码:#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int M = 110; char s[M],t[M]; int dp[M][M]; bool check(int i,int j) { if(s[i] == '(' && s[j] == ')') return true; if(s[i] == '[' && s[j] == ']') return true; return false; } void unit(int x) { switch(s[x]) { case '(': t[x] = ')'; break; case ')': t[x] = '('; break; case '[': t[x] = ']'; break; case ']': t[x] = '['; break; } } void dfs(int i,int j) { if(i > j) return ; if(check(i,j)) { if(dp[i][j] == dp[i + 1][j - 1]) dfs(i + 1,j - 1); else { for(int k = i + 1; k < j - 1; k++) { if(dp[i][j] == dp[i][k] + dp[k + 1][j]) { dfs(i,k); dfs(k + 1,j); break; } } } } else { if(dp[i][j] == dp[i][j - 1] + 1) { unit(j); dfs(i,j - 1); } else if(dp[i][j] == dp[i + 1][j] + 1) { unit(i); dfs(i + 1,j); } else { for(int k = i + 1; k < j - 1; k++) { if(dp[i][j] == dp[i][k] + dp[k + 1][j]) { dfs(i,k); dfs(k + 1,j); break; } } } } } int main() { //freopen("in","r",stdin); scanf("%s",s + 1); int n; n = strlen(s + 1); memset(dp,0,sizeof(dp)); memset(t,0,sizeof(t)); for(int i = n; i >= 1; i--) { dp[i][i] = 1; for(int j = i + 1; j <= n; j++) { if(check(i,j)) { if(i + 1 == j) dp[i][j] = 0; else dp[i][j] = dp[i + 1][j - 1]; } else dp[i][j] = min(dp[i + 1][j] + 1,dp[i][j - 1] + 1); for(int k = i + 1; k < j - 1; k++) dp[i][j] = min(dp[i][j],dp[i][k] + dp[k + 1][j]); } } //printf("%d\n",dp[1][n]); if(dp[1][n]) dfs(1,n); for(int i = 1; i <= n; i++) { if(t[i]) { if(s[i] == ')' || s[i] == ']') printf("%c%c",t[i],s[i]); else printf("%c%c",s[i],t[i]); } else printf("%c",s[i]); } puts(""); return 0; } //([]][])
E - To the MaxTime Limit:1000MS Memory Limit:10000KB 64bit IO Format:%I64d & %I64u
Description
Given a two-dimensional array of positive and negative integers, a sub-rectangle is any contiguous sub-array of size 1*1 or greater located within the whole array. The sum of a rectangle is the sum of all the elements in that rectangle. In this problem the sub-rectangle with the largest sum is referred to as the maximal sub-rectangle.
As an example, the maximal sub-rectangle of the array:
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
is in the lower left corner:
9 2
-4 1
-1 8
and has a sum of 15.
Input
The input consists of an N * N array of integers. The input begins with a single positive integer N on a line by itself, indicating the size of the square two-dimensional array. This is followed by N^2 integers separated by whitespace (spaces and newlines). These are the N^2 integers of the array, presented in row-major order. That is, all numbers in the first row, left to right, then all numbers in the second row, left to right, etc. N may be as large as 100. The numbers in the array will be in the range [-127,127].Output
Output the sum of the maximal sub-rectangle.Sample Input
4 0 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 -2题意: 给你一个矩阵,叫你找出一个最大子矩阵;Sample Output
15
题解:暴力枚举,DP(dp(i,j)表示最大子矩阵的行数在i到j,之间,然后枚举列数就好了);
AC代码:#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int M = 110; const int INF = -1e9; int dp[M][M],sum[M][M]; int main() { int n,res = INF; cin>>n; for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) { int x; scanf("%d",&x); sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + x; } for(int i = 1; i <= n; i++) { for(int j = i; j <= n; j++) { int ans = INF; for(int k = 1; k <= n; k++) { for(int p = k; p <= n; p++) { ans = max(ans,sum[j][p] - sum[i - 1][p] - sum[j][k - 1] + sum[i - 1][k - 1]); } } res = max(ans,res); } }* printf("%d\n",res); return 0; }
/**********************************************/#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int M = 110; const int INF = -1e9; int dp[M][M],sum[M][M]; int main() { int n; cin>>n; memset(sum,0,sizeof(sum)); for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { int x; scanf("%d",&x); sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + x; dp[i][j] = sum[i][j]; for(int k = 1; k < i; k++) dp[i][j] = max(dp[i][j],max(dp[k][j],sum[i][j] - sum[k][j])); for(int k = 1; k < j; k++) dp[i][j] = max(dp[i][j],max(dp[i][k],sum[i][j] - sum[i][k])); for(int k = 1; k < i; k++) { for(int p = 1; p < j; p++) { dp[i][j] = max(dp[i][j],sum[i][j] - sum[k][j] - sum[i][p] + sum[k][p]); } } } } printf("%d\n",dp[n][n]); return 0; }