10 篇文章 2 订阅

T F
(1分)

T F

T F

# 二、单选题

## 2-1

A.A(i,j)=min(A(i−1,j),A(i,j−1),A(i−1,j−1))
B.A(i,j)=F(A(min{i,j}−1,min{i,j}−1),A(max{i,j}−1,max{i,j}−1))
C.A(i,j)=F(A(i,j−1),A(i−1,j−1),A(i−1,j+1))
D.A(i,j)=F(A(i−2,j−2),A(i+2,j+2))

## 2-2

A.for k in 0 to n: for i in 0 to n: for j in n to 0
B.for i in 0 to n: for j in 0 to n: for k in 0 to n
C.for i in 0 to n: for j in n to 0: for k in n to 0
D.for i in 0 to n: for j in n to 0: for k in 0 to n

## 2-3

Length L 1 2 3 4 5 6 7 8 9 10
Price PL 1 5 8 9 10 17 17 20 23 28

A.此问题可以用动态规划求解
B.若N≤M，则有R​N​ =max{P​N​​ ,max​1≤i<N​ {R​i​​ +R​N−i​​ }}
C.若N>M，则有RN​​ =max1≤i<N​​ {R​i​​ +R​N−M }
D.算法的时间复杂度是O(N​2​​ )

# 编程题

## 7-1 单调递增最长子序列 (20 分)

### 题目描述

5
1 3 5 2 9
**输出样例:**

cpp
4


### 参考代码

#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n;
int a[n];
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
int maxl=0;
int count=0;
vector<int> v;
for(int i=0;i<n;i++)
{
v.push_back(a[i]);
for(int j=i;j<n;j++)
{
if(a[j]>(*v.rbegin()))//注意要加*
{
v.push_back(a[j]);
}
}
if(v.size()>maxl)
{
maxl=v.size();
}
vector<int>().swap(v);//清空vector的方法
}
cout<<maxl;
}

//vector<int>().swap(vecnum);


### 习题答案


#include <iostream>
using namespace std;
/*

len[i] = max {len[j] + 1 | num[i] > num[j]}, 0 <= j < i
*/
int main() {
int n;
cin >> n;
int nums[n];
int len[n];

for (int i = 0; i < n; i++)
cin >> nums[i];

len[0] = 1;
for (int i = 1; i < n; i++) { // 从左至右填表求len[i]
len[i] = 1;
for (int j = 0; j < i; j++) { //子序列前一个数字可能是nums[0..i-1],求最长子序列
if (nums[i] > nums[j] && len[j] + 1 > len[i]) {
len[i] = len[j] + 1;
}
}
}

//求以nums[0]、nums[1]...nums[n-1]结尾的序列中，最长的序列
int max = 0;
for (int i = 0; i < n; i++) {
if (len[i] > max)
max = len[i];
}

cout << max << endl;
}


len[i]=max{len[j]+1(nums[j]<nums[i],0<=j<i)}

## 7-2 租用游艇问题 (17 分)

3
5 15
7

12

### 参考代码

#include <iostream>
using namespace std;
int Smaller_one(int a,int b)//两数取较小的一个
{
if(a>b){
return b;
}
return a;
}
//1<=i<j<=n
int main()
{
int n;
cin>>n;
// 记录i到j所需要的租金，一个倒三角
int r[n+1][n+1];//下标从1开始
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
cin>>r[i][j];
}
}

//处理（逐步最优）
int min[n+1]={0};//记录从第一个站点到第i个站点的最优解（最少花费）
for(int i=2;i<=n;i++)
{
min[i]=r[1][i];
for(int j=1;j<i;j++)
{
min[i]=Smaller_one(min[i],min[j]+r[j][i]);
}
}

cout<<min[n];

}


### 习题答案

#include <iostream>
using namespace std;
const int MAXN = 300;
int cost[MAXN][MAXN]; // 费用数组

//m[i]代表从第i个租船点到终点的最小费用
//可选方案为第i个租船点直接到后面的某个租船点，
//然后从该租船点经过若干租船点到终点
//可选方案中最小的即为该子问题的解
// m[i] = max {cost[i][j] + m[j]}, i+1 <= j <= n
int m[MAXN];

int main() {
int n;
cin >> n;
int i, j;
for (i = 1; i <= n; i++) {
for (j = i + 1; j <= n; j++) {
cin >> cost[i][j];
}
}

//动态规划从右至左填表
m[n] = 0;
for (i = n - 1; i > 0; i--) {
m[i] = cost[i][i + 1] + m[i + 1];
for (j = i + 2; j <= n; j++) {
if (cost[i][j] + m[j] < m[i])
m[i] = cost[i][j] + m[j];
}
}

cout << m[1] << endl;
return 0;
}


m[i]=min{ cost[i][j]+m[j]|i<j<=n}

## 3-3 挖地雷 (22 分)

### 题目描述

xi yi //表示从xi可到yi，xi<yi。

k1-k2−…−kv //挖地雷的顺序 挖到最多的雷。

6
5 10 20 5 4 5
1 2
1 4
2 4
3 4
4 5
4 6
5 6
0 0

3-4-5-6
34

（1）用二维数组a[i][j]来记录，地雷i到地雷j的路是否为通路

s = sum[i]+num[j]
（sum[i]的初始值会随着计算挖到这个点的最大值而改变，num只是记录当前地窖地雷数的初始值）
（2）path[i]的记录方式是，i地雷的最大路径的上一个地窖是j，path[i]=j，然后j是从上一个k，path[j]=k，以此类推

·从1-2的地雷数是 5+10，途经两个点
·从小路径开啥挖，挖到第i个地雷的最大数量记录在sum[i]
sum[2]=5+10
·要确定从哪个地雷开始挖起

### 参考代码

//设nums[i]为第i个地窖埋的地雷数
//count[i]为选择第i个地窖挖时的最大地雷数，则
//count[i] = max{nums[i] + count[j] | 地窖i、j相连} i<j<=n
//path[i]记录挖完第i个地窖后，下一个菜窖选择哪一个挖的地雷数最多。

#include <iostream>
using namespace std;

const int MAX = 210;
int conn[MAX][MAX] = {0}; //记录两个菜窖是否联通
int count[MAX] = {0}; //挖到第i个地窖时的最大地雷数
int path[MAX] = {0}; //记录挖地雷的最优路径
int main() {
int n;
cin >> n;
int nums[n];
for (int i = 1; i <= n; i++)
cin >> nums[i];
while (true) {
int a, b;
cin >> a >> b;
if (a == 0 && b == 0) break;
conn[a][b] = 1;
}

//从右至左依次填表
for (int i = n; i >= 1; i--) {
count[i] = nums[i];
for (int j = i + 1; j <= n; j++) {
if (conn[i][j] == 1) {
int tmp = nums[i] + count[j];
if (tmp > count[i]) {
count[i] = tmp;
path[i] = j;
}
}
}

}

//比较从哪个菜窖开始挖地雷数最多
int max = 0; //挖到最多的地雷数
int id = 1; //从哪个菜窖开始挖
for (int i = 1; i <= n; i++) {
if (count[i] > max) {
max = count[i];
id = i;
}
}

//输出挖地雷路径
cout << id;
while (path[id] > 0) { //path[i]为0时，表示无连接，路径结束
cout << "-" << path[id];
id = path[id];
}

cout << endl << max << endl;
}


### 习题答案


#include <iostream>
using namespace std;

/*

count[i]为选择第i个地窖挖时的最大地雷数，则
count[i] = max{nums[i] + count[j] | 地窖i、j相连} i<j<=n
path[i]记录挖完第i个地窖后，下一个地窖选择哪一个挖的地雷数最多。
*/

const int MAX = 210;
int conn[MAX][MAX] = {0}; //记录两个地窖是否联通
int count[MAX] = {0}; //挖到第i个地窖时的最大地雷数
int path[MAX] = {0}; //记录挖地雷的最优路径
int main() {
int n;
cin >> n;
int nums[n];
for (int i = 1; i <= n; i++)
cin >> nums[i];
while (true) {
int a, b;
cin >> a >> b;
if (a == 0 && b == 0) break;
conn[a][b] = 1;
}

//从右至左依次填表
for (int i = n-1; i >= 1; i--) {
count[i] = nums[i];
for (int j = i + 1; j <= n; j++) {
if (conn[i][j] == 1) {
int tmp = nums[i] + count[j];
if (tmp > count[i]) {
count[i] = tmp;
path[i] = j;
}
}
}

}

//比较从哪个地窖开始挖地雷数最多
int max = 0; //挖到最多的地雷数
int id = 1; //从哪个地窖开始挖
for (int i = 1; i <= n; i++) {
if (count[i] > max) {
max = count[i];
id = i;
}
}

//输出挖地雷路径
cout << id;
while (path[id] > 0) { //path[i]为0时，表示无连接，路径结束
cout << "-" << path[id];
id = path[id];
}

cout << endl << max << endl;
}


## 3-4 最低通行费 (22 分)

5
1 4 6 8 10
2 5 7 15 17
6 8 9 18 20
10 11 12 19 21
20 23 25 29 33

109

### 参考代码

#include <iostream>
using namespace std;
int maxn=101;
int main()
{
int n;
cin>>n;
int a[n+1][n+1];
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cin>>a[i][j];
}
}
for(int i=0;i<n;i++)
{
a[i][n]=maxn;
}
for(int i=0;i<n+1;i++)
{
a[n][i]=maxn;
}
//	for(int i=0;i<n+1;i++)
//	{
//		for(int j=0;j<n+1;j++)
//		{
//			cout<<a[i][j]<<" ";
//		}
//		cout<<endl;
//	}
int sum=0;
int i=0,j=0;
//	bool flag
sum+=a[0][0];
while(!(i==n-1&&j==n-1))
{
//		if(i==0&&j==0)
//		{
//			sum+=a[i][j];


### 习题答案

#include <iostream>
using namespace std;

/*

cost[i][j]代表从方格[i,j]出发到达终点的费用，则
cost[i][j] = map[i][j] + max {cost[i+1][j], cost[i][j+1] }
*/

const int MAX = 110;
int map[MAX][MAX] = {0};
int cost[MAX][MAX] = {0};
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
cin >> map[i][j];
}
}

cost[n][n] = map[n][n];
//初始化第n行的最少费用
for (int i = n-1; i >= 1; i--)
cost[n][i] = map[n][i] + cost[n][i+1];
//初始化第n列的最少费用
for (int i = n-1; i >= 1; i--)
cost[i][n] = map[i][n] + cost[i+1][n];

//从下向上，从右向左填表
for (int i = n-1; i >= 1; i--) {
for (int j = n-1; j >= 1; j--) {
if (cost[i+1][j] < cost[i][j+1])
cost[i][j] = map[i][j] + cost[i+1][j];
else
cost[i][j] = map[i][j] + cost[i][j+1];
}
}

cout << cost[1][1] << endl;
return 0;
}

• 1
点赞
• 7
收藏
• 打赏
• 0
评论
11-18
03-26 463
12-03 2641
08-31 2610
01-11 6486
03-12 1719
02-19 4486
10-31 269
12-25 1036
11-04 85
09-24 208
05-13 3481
12-04 1100
02-23 594

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

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

GCTTTTTT

¥2 ¥4 ¥6 ¥10 ¥20

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