描述
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.
输入
Input 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.
输出
For each case, print the maximum according to rules, and one line one case.
样例输入
3 1 3 2
4 1 2 3 4
4 3 3 2 1
0
样例输出
4
10
3
O(n^2): 普通的二重循环,DP思想
LL f[N];
LL jump[N];
int main(){
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
int n;
while(scanf("%d",&n) && n){
for(int i=1;i<=n;i++) scanf("%I64d",&f[i]);
jump[1] = f[1];
LL maxc = f[1];
for(int i=2;i<=n;i++){
jump[i] = f[i];
if(jump[i] > maxc) maxc = jump[i];
for(int j=1;jif(f[j] jump[i]){
jump[i] = jump[j] + f[i];
if(jump[i]>maxc) maxc = jump[i];
}
}
printf("%I64d\n",maxc);
}
return 0;
}
O(nlogn):
目的:我们期望在前i个元素中的所有长度为len的递增子序列中找到这样一个序列,它的最大元素比arr[i+1]小,而且长度要尽量的长,如此,我们只需记录len长度的递增子序列中最大元素的最小值就能使得将来的递增子序列尽量地长。
方法:维护一个数组MaxV[i],记录长度为i的递增子序列中最大元素的最小值,并对于数组中的每个元素考察其是哪个子序列的最大元素,二分更新MaxV数组,最终i的值便是最长递增子序列的长度。这个方法真是太巧妙了,妙不可言。
转自:http://www.ahathinking.com/archives/117.html
题目1533:最长上升子序列
时间限制:1 秒
内存限制:128 兆
特殊判题:否
提交:1716
解决:360
-
题目描述:
-
给定一个整型数组, 求这个数组的最长严格递增子序列的长度。 譬如序列1 2 2 4 3 的最长严格递增子序列为1,2,4或1,2,3.他们的长度为3。
-
输入:
-
输入可能包含多个测试案例。
对于每个测试案例,输入的第一行为一个整数n(1<=n<=100000):代表将要输入的序列长度
输入的第二行包括n个整数,代表这个数组中的数字。整数均在int范围内。
-
输出:
-
对于每个测试案例,输出其最长严格递增子序列长度。
-
样例输入:
-
4
4 2 1 3
5
1 1 1 1 1
-
样例输出:
-
2
1
-
#include
#include
#include
#include
#include
#include
using namespace std;
#define N 101000
#define Min (-2147483647 - 1)
#define LL long long
LL f[N];
LL flag[N];
int len = 1;
int binary(LL t){
//找到最小的大于等于 t 的数。
int left=1,right = len;
int mid;
while(left <= right){
mid = (right + left)/2;
if(flag[mid] == t) return mid;
else if(flag[mid] > t) right = mid-1;
else left = mid + 1;
}
return left;
}
int main(){
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
int n;
while(scanf("%d",&n)!=EOF){
for(int i=1;i<=n;i++) scanf("%lld",&f[i]);
memset(flag,0,sizeof(flag));
flag[1] = f[1];
len = 1;
for(int i=2;i<=n;i++){
//printf("t: %d\n",t);
int k = binary(f[i]);
if(len else flag[k] = f[i];
}
//for(int i=1;i<=len;i++) printf("%d ",flag[i]); printf("\n");
printf("%d\n",len);
}
return 0;
}