HDU_子序列系列

HDU_1003 Max Sum

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 216899    Accepted Submission(s): 51133


Problem Description
Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14.
 

Input
The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line starts with a number N(1<=N<=100000), then N integers followed(all the integers are between -1000 and 1000).
 

Output
For each test case, you should output two lines. The first line is "Case #:", # means the number of the test case. The second line contains three integers, the Max Sum in the sequence, the start position of the sub-sequence, the end position of the sub-sequence. If there are more than one result, output the first one. Output a blank line between two cases.
 

Sample Input
  
  
2 5 6 -1 5 4 -7 7 0 6 -1 1 -6 7 -5
 

Sample Output
  
  
Case 1: 14 1 4 Case 2: 7 1 6
 
题意:求最大连续子序列以及其左右区间值。
分析:最大连续子序列。
代码清单:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int maxn = 100000 + 5;

int T;
int N;
int tcase;
int a[maxn];

int dp[maxn];

void input() {
	cin >> N;
	for(int i = 1; i <= N; ++i) {
		cin >> a[i];
	}
}

void solve() {

	int l, r = 1, maxN = -100000;
	dp[0] = 0;
	for(int i = 1; i <= N; ++i) {
		dp[i] = max(dp[i - 1] + a[i], a[i]);
		if(dp[i] > maxN) {
			maxN = dp[i];
			r = i;
		}
	}
	
	for(int i = r, sum = 0; i >= 1; --i) {
		sum += a[i];
		if(sum == maxN) l = i;
	}
	if(tcase > 1) cout << endl;
	cout << "Case " << tcase << ":" << endl;
	cout << maxN << " " << l << " " << r << endl;
}

int main() {

	cin >> T;
	for(tcase = 1; tcase <= T; ++tcase) {
		input();
		solve();
	}
	return 0;
}

HDU_1231 最大连续子序列

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 28055    Accepted Submission(s): 12696


Problem Description
给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ..., 
Nj },其中 1 <= i <= j <= K。最大连续子序列是所有连续子序列中元素和最大的一个, 
例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{ 11, -4, 13 },最大和 
为20。 
在今年的数据结构考卷中,要求编写程序得到最大和,现在增加一个要求,即还需要输出该 
子序列的第一个和最后一个元素。
 

Input
测试输入包含若干测试用例,每个测试用例占2行,第1行给出正整数K( < 10000 ),第2行给出K个整数,中间用空格分隔。当K为0时,输入结束,该用例不被处理。
 

Output
对每个测试用例,在1行里输出最大和、最大连续子序列的第一个和最后一个元 
素,中间用空格分隔。如果最大连续子序列不唯一,则输出序号i和j最小的那个(如输入样例的第2、3组)。若所有K个元素都是负数,则定义其最大和为0,输出整个序列的首尾元素。 
 

Sample Input
   
   
6 -2 11 -4 13 -5 -2 10 -10 1 2 3 4 -5 -23 3 7 -21 6 5 -8 3 2 5 0 1 10 3 -1 -5 -2 3 -1 0 -2 0
 

Sample Output
   
   
20 11 13 10 1 4 10 3 5 10 10 10 0 -1 -2 0 0 0
Hint
Hint
Huge input, scanf is recommended.
 
分析:最大连续子序列。
代码清单:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int maxn = 10000 + 5;

int K;
int a[maxn];

int dp[maxn];

void input() {

	for(int i = 1; i <= K; ++i) {
		cin >> a[i];
	}
}

void solve() {

	bool judge = false;
	for(int i = 1; i <= K; ++i) {
		if(a[i] >= 0) { judge = true; break; }
	}

	if(!judge) {
		cout << "0" << " " << a[1] << " " << a[K] << endl;
		return ; 
	}

	int l, r = 1, maxN = -100000000;
	dp[0] = 0;
	for(int i = 1; i <= K; ++i) {
		dp[i] = max(dp[i - 1] + a[i], a[i]);
		if(dp[i] > maxN) {
			maxN = dp[i];
			r = i;
		}
	}
	
	for(int i = r, sum = 0; i >= 1; --i) {
		sum += a[i];
		if(sum == maxN) l = i;
	}
	
	cout << maxN << " " << a[l] << " " << a[r] << endl;
}

int main() {

	while(cin >> K && K != 0) {
		input();
		solve();
	}
	return 0;
}

HDU_1257 最少拦截系统

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 34439    Accepted Submission(s): 13569


Problem Description
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹.
怎么办呢?多搞几套系统呗!你说说倒蛮容易,成本呢?成本是个大问题啊.所以俺就到这里来求救了,请帮助计算一下最少需要多少套拦截系统.
 

Input
输入若干组数据.每组数据包括:导弹总个数(正整数),导弹依此飞来的高度(雷达给出的高度数据是不大于30000的正整数,用空格分隔)
 

Output
对应每组数据输出拦截所有导弹最少要配备多少套这种导弹拦截系统.
 

Sample Input
   
   
8 389 207 155 300 299 170 158 65
 

Sample Output
   
   
2
 
分析:最长上升子序列。
代码清单:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int maxn = 1000000 + 5;

int n;
int a[maxn];
int dp[maxn];

void input() {
	for(int i = 0; i < n; ++i) {
		scanf("%d", &a[i]);
	}
}

void solve() {
	
	int lis = 1;
	for(int i = 0; i < n; ++i) {
		dp[i] = 1;
		for(int j = 0; j < i; ++j) {
			if(a[i] > a[j]) dp[i] = max(dp[i], dp[j] + 1);
		}
		lis = max(lis, dp[i]);
	}
	cout << lis << endl;
}

int main() {
	while(scanf("%d", &n) != EOF) {
		input();
		solve();
	}
	return 0;
}

HDU_1087 Super Jumping! Jumping! Jumping!

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 33662    Accepted Submission(s): 15237


Problem Description
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
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.
 

Output
For 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
 
分析:最大上升子序列。
代码清单:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int maxn = 1000 + 5;

int N;
long long a[maxn];
long long dp[maxn];

void input() {

	for(int i = 0; i < N; ++i) {
		cin >> a[i];
	}
}

void solve() {

	long long ans = 0;
	
	for(int i = 0; i < N; ++i) {
		dp[i] = a[i];
		for(int j = 0; j < i; ++j) {
			if(a[i] > a[j]) {
				dp[i] = max(dp[j] + a[i], dp[i]);
			}
		}
		if(dp[i] > ans) ans = dp[i];
	}

	cout << ans << endl;
}

int main() {

	while(cin >> N && N!= 0) {
		input();
		solve();
	}
	return 0;
}

HDU_1159 Common Subsequence

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 34076    Accepted Submission(s): 15527


Problem Description
A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = <x1, x2, ..., xm> another sequence Z = <z1, z2, ..., zk> is a subsequence of X if there exists a strictly increasing sequence <i1, i2, ..., ik> of indices of X such that for all j = 1,2,...,k, xij = zj. For example, Z = <a, b, f, c> is a subsequence of X = <a, b, c, f, b, c> with index sequence <1, 2, 4, 6>. Given two sequences X and Y the problem is to find the length of the maximum-length common subsequence of X and Y. 
The program input is from a text file. Each data set in the file contains two strings representing the given sequences. The sequences are separated by any number of white spaces. The input data are correct. For each set of data the program prints on the standard output the length of the maximum-length common subsequence from the beginning of a separate line. 
 

Sample Input
    
    
abcfbc abfcab programming contest abcd mnp
 

Sample Output
    
    
4 2 0
 

分析:最长公共子序列。
代码清单:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int maxn = 1000 + 5;

char s1[maxn];
char s2[maxn];
int dp[maxn][maxn];

void solve() {

	int len1 = strlen(s1);
	int len2 = strlen(s2);

	for(int i = 0; i <= len1; ++i) {
		for(int j = 0; j <= len2; ++j) {
			if(i == 0 || j == 0) dp[i][j] = 0;
			else if(s1[i - 1] == s2[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
			else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
		}
	}

	printf("%d\n", dp[len1][len2]);
}

int main() {

	while(scanf("%s%s", s1, s2) != EOF) {
		solve();
	}
	return 0;
} 








  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值