简单DP

Almost Sorted Array

We are all familiar with sorting algorithms: quick sort, merge sort, heap sort, insertion sort, selection sort, bubble sort, etc. But sometimes it is an overkill to use these algorithms for an almost sorted array.

We say an array is sorted if its elements are in non-decreasing order or non-increasing order. We say an array is almost sorted if we can remove exactly one element from it, and the remaining array is sorted. Now you are given an array a1,a2,,an

, is it almost sorted?
InputThe first line contains an integer T indicating the total number of test cases. Each test case starts with an integer n in one line, then one line with n integers a1,a2,,an.

1T2000
2n105
1ai105
There are at most 20 test cases with n>1000.OutputFor each test case, please output "`YES`" if it is almost sorted. Otherwise, output "`NO`" (both without quotes).Sample Input
3
3
2 1 7
3
3 2 1
5
3 1 4 1 5
Sample Output
YES
YES
NO

判断数列是否几乎非递增或非递减,“几乎”就是删掉一个数字后变成了非递增或非递减。
思路判断数列是最大增数列或最大减数列是否大于等于len-1就行,增数列和减数列可以有连续相等的。
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <algorithm>
 5 using namespace std;
 6 const int N = 1e5+10;
 7 const int Inf = 1<<30;
 8 int a[N], dp[N];
 9 int t, n;
10 int main(){
11     scanf("%d",&t);
12     while(t--) {
13         scanf("%d",&n);
14         for(int i = 0; i < n; i ++){
15             scanf("%d",&a[i]);
16             dp[i] = Inf;
17         }
18         for(int i = 0; i < n; i ++) {
19             *upper_bound(dp,dp+n,a[i]) = a[i];
20         }
21         int ans = upper_bound(dp,dp+n,Inf-1) - dp;
22         for(int i = 0; i < n; i ++) dp[i] = Inf;
23         for(int i = 0; i < n/2; i ++){
24             swap(a[i],a[n-i-1]);
25         }
26         for(int i = 0; i < n; i ++) {
27             *upper_bound(dp,dp+n,a[i]) = a[i];
28         }
29         int ans1 = upper_bound(dp,dp+n,Inf-1) - dp;
30         if(ans >= n-1 || ans1 >= n-1) cout << "YES
";
31         else cout << "NO
";
32         memset(a,0,sizeof(a));
33     }
34     return 0;
35 }

Greatest Common Increasing Subsequence

This is a problem from ZOJ 2432.To make it easyer,you just need output the length of the subsequence.

InputEach sequence is described with M - its length (1 <= M <= 500) and M integer numbers Ai (-2^31 <= Ai < 2^31) - the sequence itself.Outputoutput print L - the length of the greatest common increasing subsequence of both sequences.Sample Input
1

5
1 4 2 5 -12
4
-12 1 2 4
Sample Output
2

求最大公共增数列。
就是最长递增子序列和最长公共子序列的结合,dp判断下就性。
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 using namespace std;
 5 int a[550], b[550], dp[550][550];
 6 int main() {
 7     int t;
 8     scanf("%d",&t);
 9     while(t--) {
10         int n, m;
11         scanf("%d",&n);
12         for(int i = 0; i < n; i ++) scanf("%d",&a[i]);
13         scanf("%d",&m);
14         for(int i = 0; i < m; i ++) scanf("%d",&b[i]);
15         for(int i = 0; i < n; i ++) {
16             for(int j = 0; j < m; j ++) {
17                 if(a[i] == b[j]) dp[i+1][j+1] = dp[i][j] + (b[j] > b[j-1]);
18                 else dp[i+1][j+1] = max(dp[i][j+1],dp[i+1][j]);
19             }
20         }
21         cout << dp[n][m] << endl;
22         if(t)printf("
");
23         memset(dp,0,sizeof(dp));
24         memset(a,0,sizeof(a));
25         memset(b,0,sizeof(b));
26     }
27     return 0;
28 }

Advanced Fruits

The company "21st Century Fruits" has specialized in creating new sorts of fruits by transferring genes from one fruit into the genome of another one. Most times this method doesn't work, but sometimes, in very rare cases, a new fruit emerges that tastes like a mixture between both of them.
A big topic of discussion inside the company is "How should the new creations be called?" A mixture between an apple and a pear could be called an apple-pear, of course, but this doesn't sound very interesting. The boss finally decides to use the shortest string that contains both names of the original fruits as sub-strings as the new name. For instance, "applear" contains "apple" and "pear" (APPLEar and apPlEAR), and there is no shorter string that has the same property.

A combination of a cranberry and a boysenberry would therefore be called a "boysecranberry" or a "craboysenberry", for example.

Your job is to write a program that computes such a shortest name for a combination of two given fruits. Your algorithm should be efficient, otherwise it is unlikely that it will execute in the alloted time for long fruit names.

InputEach line of the input contains two strings that represent the names of the fruits that should be combined. All names have a maximum length of 100 and only consist of alphabetic characters.

Input is terminated by end of file.
OutputFor each test case, output the shortest name of the resulting fruit on one line. If more than one shortest name is possible, any one is acceptable.
Sample Input
apple peach
ananas banana
pear peach
Sample Output
appleach
bananas
pearch


求一长度最小的字符串,要包含输入的两个字符串。
最长公共子序列,不过要标记下。


 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 using namespace std;
 5 const int N = 110;
 6 int dp[N][N], mark[N][N], len1, len2;
 7 char str1[N], str2[N];
 8 
 9 void LCS(){
10     memset(dp,0,sizeof(dp));
11     for(int i = 0; i <= len1; i ++)
12         mark[i][0] = 1;
13     for(int i = 0; i <= len2; i ++)
14         mark[0][i] = -1;
15     for(int i = 1; i <= len1; i ++){
16         for(int j = 1; j <= len2; j ++){
17             if(str1[i-1] == str2[j-1]){
18                 dp[i][j] = dp[i-1][j-1]+1;
19                 mark[i][j] = 0;
20             }else if(dp[i-1][j] >= dp[i][j-1]){
21                 dp[i][j] = dp[i-1][j];
22                 mark[i][j] = 1;
23             }else {
24                 dp[i][j] = dp[i][j-1];
25                 mark[i][j] = -1;
26             }
27         }
28     }
29 }
30 void printLCS(int i, int j) {
31     if(!i && !j)return;
32     if(mark[i][j] == 0){
33         printLCS(i-1,j-1);
34         printf("%c",str1[i-1]);
35     }else if(mark[i][j] == 1){
36         printLCS(i-1,j);
37         printf("%c",str1[i-1]);
38     }else {
39         printLCS(i,j-1);
40         printf("%c",str2[j-1]);
41     }
42 }
43 int main() {
44     while(scanf("%s%s",str1,str2)!=EOF){
45         len1 = strlen(str1); len2 = strlen(str2);
46         LCS();
47         printLCS(len1,len2);
48         printf("
");
49     }
50     return 0;
51 }

Super Jumping! Jumping! Jumping!

Nowadays, a kind of chess game called “Super Jumping! Jumping! Jumping!” is very popular in HDU. Maybe you are a good boy, and know little about this game, so I introduce it to you now.



The game can be played by two or more than two players. It consists of a chessboard(棋盘)and some chessmen(棋子), and all chessmen are marked by a positive integer or “start” or “end”. The player starts from start-point and must jumps into end-point finally. In the course of jumping, the player will visit the chessmen in the path, but everyone must jumps from one chessman to another absolutely bigger (you can assume start-point is a minimum and end-point is a maximum.). And all players cannot go backwards. One jumping can go from a chessman to next, also can go across many chessmen, and even you can straightly get to end-point from start-point. Of course you get zero point in this situation. A player is a winner if and only if he can get a bigger score according to his jumping solution. Note that your score comes from the sum of value on the chessmen in you jumping path.
Your task is to output the maximum value according to the given chessmen list.

InputInput contains multiple test cases. Each test case is described in a line as follow:
N value_1 value_2 …value_N
It is guarantied that N is not more than 1000 and all value_i are in the range of 32-int.
A test case starting with 0 terminates the input and this test case is not to be processed.
OutputFor each case, print the maximum according to rules, and one line one case.
Sample Input
3 1 3 2
4 1 2 3 4
4 3 3 2 1
0
Sample Output
4
10
3

求一增子序列,并把它的值相加,总和最大的数。
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 using namespace std;
 5 const int N = 1010;
 6 int dp[N], a[N], n;
 7 int main(){
 8     while(scanf("%d",&n)&&n) {
 9         for(int i = 0; i < n; i ++) scanf("%d",&a[i]);
10         int ans = 0;
11         for(int i = 0; i < n; i ++) {
12             dp[i] = a[i];
13             for(int j = 0; j < i; j ++) {
14                 if(a[i] > a[j]) dp[i] = max(dp[i],dp[j]+a[i]);
15             }
16             ans = max(dp[i],ans);
17         }
18         printf("%d
",ans);
19         memset(dp,0,sizeof(dp));
20         memset(a,0,sizeof(a));
21     }
22     return 0;
23 }
原文地址:https://www.cnblogs.com/xingkongyihao/p/7230740.html