程序设计算法竞赛基础——练习4解题报告

程序设计算法竞赛基础——练习4解题报告

1001 数塔

Problem Description

在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这样描述的:

有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?

1001

已经告诉你了,这是个DP的题目,你能AC吗?

Input

输入数据首先包括一个整数C,表示测试实例的个数,每个测试实例的第一行是一个整数N(1 <= N <= 100),表示数塔的高度,接下来用N行数字表示数塔,其中第i行有个i个整数,且所有的整数均在区间[0,99]内。

Output

对于每个测试实例,输出可能得到的最大和,每个实例的输出占一行。

Sample Input

1
5
7
3 8
8 1 0 
2 7 4 4
4 5 2 6 5

Sample Output

30

Source

2006/1/15 ACM程序设计期末考试

解题思路

从底层依次向上判断,a[i] [j]选择max(a[i+1] [j], a[i+1] [j+1])

代码实现

#include
#define max(a,b) (a>b)?a:b
using namespace std;

int n, c;
int dp[105][105];

int main() {
	cin >> c;
	while(c--) {
		cin >> n;
		for(int i = 1; i <= n; i++) {
			for(int j = 1; j <= i; j++) {
				cin >> dp[i][j];
			}
		}
		for(int i = n - 1; i > 0; i--) {
			for(int j = 1; j <= i; j++) {
				dp[i][j] += max(dp[i+1][j],dp[i+1][j+1]);
			}
		}
		cout << dp[1][1] << endl;
	}
	return 0;
}

1002 连续最大积

Problem Description

小明和他的好朋友小西在玩一个游戏,由电脑随机生成一个由-2,0,2三个数组成的数组,并且约定,谁先算出这个数组中某一段连续元素的积的最大值,就算谁赢!

比如我们有如下随机数组:
2 2 0 -2 0 2 2 -2 -2 0
在这个数组的众多连续子序列中,2 2 -2 -2这个连续子序列的积为最大。

现在小明请你帮忙算出这个最大值。

Input

第一行输入一个正整数T,表示总共有T组数据(T <= 200)。
接下来的T组数据,每组数据第一行输入N,表示数组的元素总个数(1<= N <= 10000)。
再接下来输入N个由0,-2,2组成的元素,元素之间用空格分开。

Output

对于每组数据,先输出Case数。
如果最终的答案小于等于0,直接输出0
否则若答案是2^x ,输出x即可。
每组数据占一行,具体输出格式参见样例。

Sample Input

2
2
-2 0
10
2 2 0 -2 0 2 2 -2 -2 0

Sample Output

Case #1: 0
Case #2: 4

Source

2013金山西山居创意游戏程序挑战赛——复赛(2)

解题思路

0为分界点,将序列分为若干段,设每段最大为2^X,则输出maxX

若某段有偶数个**-2**,则**X = **该段长

若某段有奇数个**-2**,则**X = **该段长 - 该段中-2离边界最近距离

代码实现

#include
#define max(a,b) (a>b)?a:b
#define min(a,b) (a start; i--) {
		if(arr[i] < 0) {
			minn = min(minn,end-i);
			break;
		}
	}
	return minn;
}

int main() {
	int t;
	cin >> t;
	for(int kase = 1; kase <= t; kase++) {
		cin >> n;
		for(int i = 0; i < n; i++) cin >> arr[i];
		maxsum = 0, temp = 0;
		int fs = 0;
		int start = -1;
		for(int i = 0; i < n; i++) {
			if(arr[i] == 0) {
				if(fs % 2 == 1) temp -= jug(start, i);
				maxsum = max(maxsum,temp);
				start = i;
				temp = 0;
				fs = 0;
			} else {
				temp++;
				if(arr[i] < 0) fs++;
			}
		}
        //若序列最后一个数不是0还需要再进行一次判断
		if(arr[n-1] != 0) {
			if(fs % 2 == 1) temp -= jug(start, n);
			maxsum = max(maxsum,temp);
		}
		cout << "Case #" << kase << ": " << maxsum << endl;
	}
	return 0;
}

1003 Ignatius and the Princess IV

Problem Description

“OK, you are not too bad, em… But you can never pass the next test.” feng5166 says.

“I will tell you an odd number N, and then N integers. There will be a special integer among them, you have to tell me which integer is the special one after I tell you all the integers.” feng5166 says.

“But what is the characteristic of the special integer?” Ignatius asks.

“The integer will appear at least (N+1)/2 times. If you can’t find the right integer, I will kill the Princess, and you will be my dinner, too. Hahahaha…” feng5166 says.

Can you find the special integer for Ignatius?

Input

The input contains several test cases. Each test case contains two lines. The first line consists of an odd integer N(1<=N<=999999) which indicate the number of the integers feng5166 will tell our hero. The second line contains the N integers. The input is terminated by the end of file.

Output

For each test case, you have to output only one line which contains the special number you have found.

Sample Input

5
1 3 2 3 3
11
1 1 1 1 1 5 5 5 5 5 5
7
1 1 1 1 1 1 1

Sample Output

3
5
1

Author

Ignatius.L

解题思路

将输入数排序寻找出现(n+1)/2次的是哪个数就行

代码实现

#include
#include
#include
using namespace std;

const int maxn = 1e6 + 5;
int arr[maxn];

int main(){
	int n;
	while(cin >> n) {
		int maxtime = (n + 1) / 2;
		int tk = 0, key = 0;
		for(int i = 0; i < n; i++) {
			scanf("%d", &arr[i]);
		}
		sort(arr, arr + n);
		for(int i = 0; i < n; i++) {
			if(arr[i] != key) {
				tk = 1;
				key = arr[i];
			}
			else {
				tk++;
                //当数key已经出现maxtime次时输出key并结束寻找
				if(tk >= maxtime) {
					cout << key << endl;
					break;
				}
			}
		}
	}
	return 0;
}

1004 Monkey and Banana

Problem Description

A group of researchers are designing an experiment to test the IQ of a monkey. They will hang a banana at the roof of a building, and at the mean time, provide the monkey with some blocks. If the monkey is clever enough, it shall be able to reach the banana by placing one block on the top another to build a tower and climb up to get its favorite food.

The researchers have n types of blocks, and an unlimited supply of blocks of each type. Each type-i block was a rectangular solid with linear dimensions (xi, yi, zi). A block could be reoriented so that any two of its three dimensions determined the dimensions of the base and the other dimension was the height.

They want to make sure that the tallest tower possible by stacking blocks can reach the roof. The problem is that, in building a tower, one block could only be placed on top of another block as long as the two base dimensions of the upper block were both strictly smaller than the corresponding base dimensions of the lower block because there has to be some space for the monkey to step on. This meant, for example, that blocks oriented to have equal-sized bases couldn’t be stacked.

Your job is to write a program that determines the height of the tallest tower the monkey can build with a given set of blocks.

Input

The input file will contain one or more test cases. The first line of each test case contains an integer n,
representing the number of different blocks in the following data set. The maximum value for n is 30.
Each of the next n lines contains three integers representing the values xi, yi and zi.
Input is terminated by a value of zero (0) for n.

Output

For each test case, print one line containing the case number (they are numbered sequentially starting from 1) and the height of the tallest possible tower in the format “Case case: maximum height = height”.

Sample Input

1
10 20 30
2
6 8 10
5 5 5
7
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 7
5
31 41 59
26 53 58
97 93 23
84 62 64
33 83 27
0

Sample Output

Case 1: maximum height = 40
Case 2: maximum height = 21
Case 3: maximum height = 28
Case 4: maximum height = 342

Source

University of Ulm Local Contest 1996

解题思路

将每块石头分成三个情况存储,然后把所有石头按体积从小到大排序

设有石头ab,他们的底边长设为x,y
只有min(a.x, a.y) < min(b.x, b.y) && max(a.x, a.y) < max(b.x, b.y)时 石头b才能放在石头a的下面

代码实现

#include
#include
#include
using namespace std;

//l和d为石头底边, h为石头高
struct INF {
	int l, d, h;

	INF() {}
	INF(const int a, const int b, const int c) : l(a), d(b), h(c) {}

    //maxside输出底面最长边
	int maxside() {
		return (l>d)?l:d;
	}

    //minside输出底面最短边
	int minside() {
		return (l

1005 Bone Collector

Problem Description

Many years ago , in Teddy’s hometown there was a man who was called “Bone Collector”. This man like to collect varies of bones , such as dog’s , cow’s , also he went to the grave …
The bone collector had a big bag with a volume of V ,and along his trip of collecting there are a lot of bones , obviously , different bone has different value and different volume, now given the each bone’s value along his trip , can you calculate out the maximum of the total value the bone collector can get ?

1005

Input

The first line contain a integer T , the number of cases.
Followed by T cases , each case three lines , the first line contain two integer N , V, (N <= 1000 , V <= 1000 )representing the number of bones and the volume of his bag. And the second line contain N integers representing the value of each bone. The third line contain N integers representing the volume of each bone.

Output

One integer per line representing the maximum of the total value (this number will be less than 2^31).

Sample Input

1
5 10
1 2 3 4 5
5 4 3 2 1

Sample Output

14

Author

Teddy

Source

HDU 1st “Vegetable-Birds Cup” Programming Open Contest

解题思路

利用结构体储存骨头数据,把骨头按体积排序

代码实现

#include
#include
#include
using namespace std;

struct INF{
	int value, volume;
	
	bool operator < (const INF& t) const {
		return volume < t.volume;
	}
};

const int maxn = 1e3 + 5;
INF arr[maxn];
int dp[maxn];

int main(){
	int c;
	scanf("%d", &c);
	while(c--){
		int n, v;
		scanf("%d %d", &n, &v);
		for(int i = 0; i < n; i++) scanf("%d", &arr[i].value);
		for(int i = 0; i < n; i++) scanf("%d", &arr[i].volume);
		sort(arr, arr + n);
		memset(dp, 0, sizeof(dp));
		for(int i = n - 1; i >= 0; i--) {
			for(int j = v; j >= arr[i].volume; j--) {
				dp[j] = max(dp[j], dp[j-arr[i].volume] + arr[i].value);
			}
		}
		printf("%d\n", dp[v]);
	}
	return 0;
}

1006 饭卡

Problem Description

电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额。如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够)。所以大家都希望尽量使卡上的余额最少。
某天,食堂中有n种菜出售,每种菜可购买一次。已知每种菜的价格以及卡上的余额,问最少可使卡上的余额为多少。

Input

多组数据。对于每组数据:
第一行为正整数n,表示菜的数量。n<=1000。
第二行包括n个正整数,表示每种菜的价格。价格不超过50。
第三行包括一个正整数m,表示卡上的余额。m<=1000。

n=0表示数据结束。

Output

对于每组输入,输出一行,包含一个整数,表示卡上可能的最小余额。

Sample Input

1
50
5
10
1 2 3 2 1 1 2 3 2 1
50
0

Sample Output

-45
32

Source

UESTC 6th Programming Contest Online

解题思路

将菜按单价从小到大排序,最贵的菜必须买,而且必须留到最后再买

代码实现

#include
#include
#include
#include
using namespace std;

const int maxn = 1e3 + 5;
int arr[maxn];
int dp[maxn];

int mymin(const int a, const int b) {
	if(b < 0) return a;
	return (a= 0; i--) {
			for(int j = m - 5; j >= arr[i]; j--) {
				dp[j] = mymin(dp[j], dp[j - arr[i]] - arr[i]);
			}
		}
        //买完其他菜后剩余余额+预先留下的5块-最贵菜的菜价 就是所求最小值
		printf("%d\n", dp[m-5] - arr[n-1] + 5);
	}
	return 0;
}

1007 最少拦截系统

Problem Description

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

Input

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

Output

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

Sample Input

8 389 207 155 300 299 170 158 65

Sample Output

2

Source

浙江工业大学第四届大学生程序设计竞赛

解题思路

当现有拦截系统不能满足需求时再增加一台新的拦截系统,由于是新加的,所以新拦截系统能拦截的高度一定比旧的高,所以每次优先使用旧的拦截

代码实现

#include
#include
using namespace std;

int arr;
vector ju;

int main(){
	int n;
	while(scanf("%d", &n) != EOF) {
		ju.clear();
		for(int i = 0; i < n; i++) {
			scanf("%d", &arr);
            //temp判断现有拦截系统能否拦截
			bool temp = false;
			for(int j = 0; j < ju.size() && !temp; j++) {
                //拦截成功的系统的最大拦截高度会因此下降
				if(arr < ju[j]) {
					ju[j] = arr;
					temp = true;
				}
			}
            //不能拦截就新增一台拦截系统
			if(!temp) ju.push_back(arr);
		}
		printf("%d\n", ju.size());
	}
	return 0;
}

你可能感兴趣的:(练习)