简单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.

1≤T≤2000

2≤n≤105

1≤ai≤105

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\n";
31         else cout << "NO\n";
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("\n");
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 // char str1[110], str2[110], dp[110][110];
 6 // int main(){
 7 //     while(scanf("%s%s",str1,str2)!=EOF) {
 8 //         int len1 = strlen(str1), len2 = strlen(str2);
 9 //         for(int i = 0; i < len1; i ++) {
10 //             for(int j = 0; j < len2; j ++) {
11 //                 if(str1[i] == str2[j]) dp[i+1][j+1] = dp[i][j]+1;
12 //                 else dp[i+1][j+1] = max(dp[i+1][j],dp[i][j+1]);
13 //             }
14 //         }
15 //         int ans1 = 0, ans2 = 0;
16 //         for(int i = 1; i <= len2; i ++){
17 //             if(dp[len1][i] == i) ans2 = i;
18 //         }
19 //         for(int i = 1; i <= len1; i ++){
20 //             if(dp[i][len2] == i) ans1 = i;
21 //         }
22 //         if(ans1 > ans2){
23 //             printf("%s%s\n",str2,str1+ans1);
24 //         }else printf("%s%s\n",str1,str2+ans2);
25 //         memset(str2,0,sizeof(str2));
26 //         memset(str1,0,sizeof(str1));
27 //         memset(dp,0,sizeof(dp));
28 //     }
29 //     return 0;
30 // }
31
32
33
34 #include <iostream>
35 #include <stdio.h>
36 #include <string.h>
37 using namespace std;
38 const int N = 110;
39 int dp[N][N], mark[N][N], len1, len2;
40 char str1[N], str2[N];
41
42 void LCS(){
43     memset(dp,0,sizeof(dp));
44     for(int i = 0; i <= len1; i ++)
45         mark[i][0] = 1;
46     for(int i = 0; i <= len2; i ++)
47         mark[0][i] = -1;
48     for(int i = 1; i <= len1; i ++){
49         for(int j = 1; j <= len2; j ++){
50             if(str1[i-1] == str2[j-1]){
51                 dp[i][j] = dp[i-1][j-1]+1;
52                 mark[i][j] = 0;
53             }else if(dp[i-1][j] >= dp[i][j-1]){
54                 dp[i][j] = dp[i-1][j];
55                 mark[i][j] = 1;
56             }else {
57                 dp[i][j] = dp[i][j-1];
58                 mark[i][j] = -1;
59             }
60         }
61     }
62 }
63 void printLCS(int i, int j) {
64     if(!i && !j)return;
65     if(mark[i][j] == 0){
66         printLCS(i-1,j-1);
67         printf("%c",str1[i-1]);
68     }else if(mark[i][j] == 1){
69         printLCS(i-1,j);
70         printf("%c",str1[i-1]);
71     }else {
72         printLCS(i,j-1);
73         printf("%c",str2[j-1]);
74     }
75 }
76 int main() {
77     while(scanf("%s%s",str1,str2)!=EOF){
78         len1 = strlen(str1); len2 = strlen(str2);
79         LCS();
80         printLCS(len1,len2);
81         printf("\n");
82     }
83     return 0;
84 }

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\n",ans);
19         memset(dp,0,sizeof(dp));
20         memset(a,0,sizeof(a));
21     }
22     return 0;
23 }
时间: 2024-10-17 01:19:15

简单DP的相关文章

POJ 3250 Bad Hair Day 简单DP 好题

Description Some of Farmer John's N cows (1 ≤ N ≤ 80,000) are having a bad hair day! Since each cow is self-conscious about her messy hairstyle, FJ wants to count the number of other cows that can see the top of other cows' heads. Each cow i has a sp

hdu1207 汉诺塔II 简单dp

本文出自:http://blog.csdn.net/svitter 题意:汉诺塔,多了一根柱子,问你寻找最快的移动次数. dp [ n ] = dp [ n - j ] * 2 + pow( 2, j ) - 1; 就是把j个汉诺塔移到一根上dp[ n - j ],然后就是普通的汉诺塔问题,即2^n - 1次移动, 然后把剩下的移动过去dp [ n - j ]. 注意pow(2, j )可能超出long long int范围.写二的次方的时候也可用移位算法. #include <iostream

POJ1088:滑雪(简单dp)

题目链接:  http://poj.org/problem?id=1088 题目要求: 一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小.求可以滑落的最长长度. 题目解析: 首先要先排一下序,因为只能高度递减才能滑行.之后就很简单了,就是简单DP. 即:要求的滑坡是一条节点递减并依次相邻的最长路径,可以先根据高度将所有的点进行排序,在i点的时候,遍历0~i-1个点(升序排序,i前面的点的高度一定小于等于i),取相邻点间的大的路径长度 代码如下: #include <iostream

hdu 1087 简单dp

思路和2391一样的.. <span style="font-size:24px;">#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; const int inf=(0x7f7f7f7f); int main() { int a; int s[10005]; int w[10005];

hdu1087 简单DP

I - 简单dp 例题扩展 Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description Nowadays, a kind of chess game called “Super Jumping! Jumping! Jumping!” is very popular in HD

2014 HDU多校弟九场I题 不会DP也能水出来的简单DP题

听了ZWK大大的思路,就立马1A了 思路是这样的: 算最小GPA的时候,首先每个科目分配到69分(不足的话直接输出GPA 2),然后FOR循环下来使REMAIN POINT减少,每个科目的上限加到100即可 算最大GPA的时候,首先每个科目分配到60分,然后FOR循环下来使REMAIN POINT减少,每个科目的上限加到85即可,如果还有REMAIN POINT,就FOR循环下来加到100上限即可 不会DP 阿 QAQ 过段时间得好好看DP了  =  = 于是默默的把这题标记为<水题集> //

Codeforces 41D Pawn 简单dp

题目链接:点击打开链接 给定n*m 的矩阵 常数k 下面一个n*m的矩阵,每个位置由 0-9的一个整数表示 问: 从最后一行开始向上走到第一行使得路径上的和 % (k+1) == 0 每个格子只能向或走一步 求:最大的路径和 最后一行的哪个位置作为起点 从下到上的路径 思路: 简单dp #include <cstdio> #include <algorithm> #include<iostream> #include<string.h> #include &

HDU 4826 简单DP

Problem Description 度度熊是一只喜欢探险的熊,一次偶然落进了一个m*n矩阵的迷宫,该迷宫只能从矩阵左上角第一个方格开始走,只有走到右上角的第一个格子才算走出迷宫,每一次只能走一格,且只能向上向下向右走以前没有走过的格子,每一个格子中都有一些金币(或正或负,有可能遇到强盗拦路抢劫,度度熊身上金币可以为负,需要给强盗写欠条),度度熊刚开始时身上金币数为0,问度度熊走出迷宫时候身上最多有多少金币? Input 输入的第一行是一个整数T(T < 200),表示共有T组数据.每组数据的

UVA - 11584 划分字符串的回文串子串; 简单dp

/** 链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34398 UVA - 11584 划分字符串的回文串子串: 简单dp 题目大意: 给一个字符串, 要求把它分割成若干个子串,使得每个子串都是回文串.问最少可以分割成多少个. 定义:dp[i]表示前0~i内的字符串划分成的最小回文串个数: dp[i] = min(dp[j]+1 | j+1~i是回文串); 先预处理flag[i][j]表示以i~j内的字符串为回文串

poj 2193 Lenny&#39;s Lucky Lotto Lists 简单dp

//poj 2193 //sep9 #include <iostream> using namespace std; typedef __int64 INT; INT dp[16][2048]; int n,m; int main() { int cases,t=0; scanf("%d",&cases); while(cases--){ scanf("%d%d",&n,&m); memset(dp,0,sizeof(dp));