1. 程式人生 > >10.19—動態規劃 //最長公共子序列//防衛導彈//田忌賽馬//計算矩陣連乘積//最長子序列的長度

10.19—動態規劃 //最長公共子序列//防衛導彈//田忌賽馬//計算矩陣連乘積//最長子序列的長度

1.最長公共子序列

描述:一個給定序列的子序列是在該序列中刪去若干元素後得到的序列。確切地說,若給定序列X=<x1, x2,…, xm>,則另一序列Z=<z1, z2,…, zk>是X的子序列是指存在一個嚴格遞增的下標序列 <i1, i2,…, ik>,使得對於所有j=1,2,…,k有:

Xij = Zj
如果一個序列S即是A的子序列又是B的子序列,則稱S是A、B的公共子序列。
求A、B所有公共子序列中最長的序列的長度。

輸入:輸入共兩行,每行一個由字母和數字組成的字串,代表序列A、B。A、B的長度不超過200個字元。

輸出:一個整數,表示最長各個子序列的長度。格式:printf("%d\n");

輸入樣例

programming
contest

輸出樣例

2

#include<iostream>
#include<string.h>
#include<math.h>
using namespace std;

int main(){
	int ans = 0;
    char a[205], b[205];
	int l[205][205] = {0};
	gets(a);
	gets(b);

	for(int i = 1; i <= strlen(a); i++){
		for(int j = 1; j <= strlen(b); j++){
			if(a[i-1] == b[j-1]){
			    l[i][j] = l[i-1][j-1] + 1;
			}
			else{
				l[i][j] = max(l[i][j-1], l[i-1][j]);
			}
		}
	}
	cout << l[strlen(a)][strlen(b)] << endl;
}

2.防衛導彈

描述:一種新型的防衛導彈可截擊多個攻擊導彈。它可以向前飛行,也可以用很快的速度向下飛行,可以毫無損傷地截擊進攻導彈,但不可以向後或向上飛行。但有一個缺點,儘管它發射時可以達到任意高度,但它只能截擊比它上次截擊導彈時所處高度低或者高度相同的導彈。現對這種新型防衛導彈進行測試,在每一次測試中,發射一系列的測試導彈(這些導彈發射的間隔時間固定,飛行速度相同),該防衛導彈所能獲得的資訊包括各進攻導彈的高度,以及它們發射次序。現要求編一程式,求在每次測試中,該防衛導彈最多能截擊的進攻導彈數量,一個導彈能被截擊應滿足下列兩個條件之一:
a)它是該次測試中第一個被防衛導彈截擊的導彈;
b)它是在上一次被截擊導彈的發射後發射,且高度不大於上一次被截擊導彈的高度的導彈。

輸入:多個測例。
每個測例第一行是一個整數n(n不超過100),第二行n個整數表示導彈的高度(數字的順序即發射的順序)。
n=0表示輸入結束。

輸出:每個測例在單獨的一行內輸出截擊導彈的最大數目。

輸入樣例

5
5 6 100 6 61
0

輸出樣例

2

#include<iostream>
using namespace std;

int main(){
	int n;
	int arr[300];
	int l[300];
	int max;
	while(cin >> n && n){
		for(int i = 0; i < n; i++){
		    cin >> arr[i];
			l[i] = 1;
		}
		l[n] = 1;

		for(int i = 1; i < n; i++){
			for(int j = 0; j < i; j++){
				if(arr[j] >= arr[i] && l[i] <= l[j]){
				    l[i] = l[j] + 1;
				}
			}
		}
		max = l[0];
		for(int i = 1; i < n; i++){
			if(max < l[i]){
			    max = l[i];
			}
		}
		cout << max << endl;
	}
}

3.田忌賽馬

描述:田忌與齊王賽馬,雙方各有n匹馬參賽(n<=100),每場比賽賭注為1兩黃金,現已知齊王與田忌的每匹馬的速度,並且齊王肯定是按馬的速度從快到慢出場,現要你寫一個程式幫助田忌計算他最好的結果是贏多少兩黃金(輸用負數表示)。
Tian Ji and the king play horse racing, both sides have n horse (n is no more the 100), every game a bet of 1 gold, now known king and Tian Ji each horse's speed, and the king is definitely on the horse speed from fast to slow, we want you to write a program to help Tian Ji his best result is win the number gold (lost express with the negative number).

輸入:多個測例。
每個測例三行:第一行一個整數n,表示雙方各有n匹馬;第二行n個整數分別表示田忌的n匹馬的速度;第三行n個整數分別表示齊王的n匹馬的速度。
n=0表示輸入結束。
A plurality of test cases.
Each test case of three lines: the first line contains an integer n, said the two sides each have n horse; second lines of N integers n Tian Ji horse speed; third lines of N integers King n horse speed.
N = 0 indicates the end of input.

輸出:每行一個整數,田忌最多能贏多少兩黃金。
how many gold the tian ji win

輸入樣例

3
92 83 71
95 87 74
2
20 20
20 20
2
20 19
22 18
3
20 20 10
20 20 10
0

輸出樣例

1
0
0
0

#include<iostream>
#include<algorithm>
using namespace std;

int main(){
	int n;
	int arr1[300],arr2[300];
	int l[300][300];
	while(cin >> n && n){
		for(int i = 0; i < n; i++){
		    cin >> arr1[i];
		}
		for(int i = 0; i < n; i++){
			cin >> arr2[i];
		}
		sort(arr1, arr1+n, greater<int>());
		sort(arr2, arr2+n, greater<int>());
		for(int i = 0; i <= n; i++){
			for(int j = 0; j <= n; j++){
			    l[i][j] = 0;
			}
		}

		for(int i = 1; i <= n; i++){
			for(int j = 1; j <= i; j++){
				if(arr1[j-1] > arr2[i-1]){
				    l[j][i] = l[j-1][i-1] + 1;
				}
				else if(arr1[j-1] == arr2[i-1]){
				    l[j][i] = max(l[j-1][i-1], l[j-1][i] - 1);
				}
				else{
				    l[j][i] = l[j-1][i] - 1;
				}
			}
		}
		cout << l[n][n] << endl;
	}
}

4.計算矩陣連乘積

描述:在科學計算中經常要計算矩陣的乘積。矩陣A和B可乘的條件是矩陣A的列數等於矩陣B的行數。若A是一個p×q的矩陣,B是一個q×r的矩陣,則其乘積C=AB是一個p×r的矩陣。計算C=AB總共需要p×q×r次乘法。
現在的問題是,給定n個矩陣{A1,A2,…,An}。其中Ai與Ai+1是可乘的,i=1,2,…,n-1。
要求計算出這n個矩陣的連乘積A1A2…An最少需要多少次乘法。

輸入:輸入資料的第一行是一個整樹n(0 < n <= 10),表示矩陣的個數。
接下來的n行每行兩個整數p,q( 0 < p,q < 100),分別表示一個矩陣的行數和列數。

輸出:輸出一個整數:計算連乘積最少需要乘法的次數。

輸入樣例

10
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11

輸出樣例

438

#include<iostream>
using namespace std;



int main(){
    int tmp;
	int i, j, r, k, t;
    int n;
    int arr[100];
    int l[100][100] = {0};
	
	cin >> n;
	for(int i = 0; i < n ;i++){
	    cin >> arr[i] >> tmp;
	}
	arr[n] = tmp;

	for(r = 1; r < n; r++){
		for(i = 1; i < n; i++){
			j = i+r;
			l[i][j] = l[i+1][j] + arr[i-1]*arr[i]*arr[j];
			for(k = i+1; k < j; k++){
			    t = l[i][k] + l[k+1][j] +arr[i-1]*arr[k]*arr[j];
				if(t < l[i][j]){
				    l[i][j] = t;
				}
			}
		}
	}
	cout << l[1][n] << endl;
}

5.最長子序列的長度

描述:給定一個序列,求它的最長遞增子序列的長度
輸入:先輸入一個正整數n,表示序列的長度,再輸入n個整數表示這個序列

輸出:輸出它的最長遞增子序列的長度

輸入樣例

7
3 8 6 9 12 100 30

輸出樣例

5

#include<iostream>
using namespace std;

int main(){
    int n, i, j;
	int ans;
	int arr[1000], list[1000];
    
    cin >> n;
	for(i = 0; i < n; i++){
	    cin >> arr[i];
	    list[i] = 1;
	}

	for(i = 1, ans = 1; i < n; i++){
		for(j = 0; j < i; j++){
			if(arr[j] < arr[i] && list[j]+1 > list[i]){
			    list[i] = list[j] + 1;
			}
            if(list[i] > ans){
		        ans = list[i];
		    }
		}
	}

	cout << ans << endl;
}