SDU程序设计思维与实践作业Week11

本文详细解析了SDU程序设计思维与实践作业Week11的必做题及选做题,包括东东与ATM、东东开车了等题目,提供了C++代码实现,涉及算法设计、数据结构、多重背包、背包问题等核心概念。

必做题11-1

题目

题目
input&&output
input&&output
Sample

#input:
50 10
#output:
8

题解

本题直接暴力即可
我们模拟到第i年 东东会有多少存款,是否比第i年的房价高
注意每次计算时要记录原值,以便于买不起时的回溯

C++代码

#include<iostream>

using namespace std;

int main(){
	float N,K;
	cin>>N>>K;
	float sum=200,old;
	for(int i=0 ;i<20;i++){
		old = sum;
		sum-=(i+1)*N;
		if(sum<=0){
			cout<<i+1<<endl;
			return 0;
		}
		sum=old;
		sum*=(1+K/100);
	}
	cout<<"Impossible\n";
	return 0;
}

必做题11-2

题目

题目
input&&output
input&&output
Sample

#input:
4
0 0 0 0
0 0 0 0
0 1 0 0
0 0 0 0
0 0 0 0
0 1 0 0
0 0 0 0
0 0 0 0
#output:
1

题解

本题我们只需要找出转90度坐标的变化规则就好了,然后遍历三次判断是否需要旋转(是否与原矩阵相同)
90度规则:
	[i,j]旋转90度对应 [j,n-i+1]

C++代码

#include<iostream>

using namespace std;
const int maxn = 25;
int tmp[maxn][maxn];
int st[maxn][maxn];
int ret[maxn][maxn];

void solve(int n){
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			tmp[i][j] = st[i][j];
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++){
			st[j][n-i+1] = tmp[i][j];
		}
}
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++){
			tmp[i][j] = 0;
			ret[i][j] = 0;
			st[i][j] = 0;
		}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			cin>>st[i][j];
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			cin>>ret[i][j];
	bool ans = true;
	for(int i=0;i<4;i++){
		ans = true;
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				if(ret[i][j] != st[i][j]) ans=false;
		if(ans){
			cout<<i<<endl;
			return 0;
		}
		solve(n);
	}
	cout<<-1<<endl;
	return 0;
}

必做题11-3

题目

题目
input&&output
input&&output
Sample

#input:
NS BFW, JAJSYX TK NRUTWYFSHJ FWJ YMJ WJXZQY TK YWNANFQ HFZXJX
#output:
IN WAR, EVENTS OF IMPORTANCE ARE THE RESULT OF TRIVIAL CAUSES

题解

本题读需要读一行 getline(cin,str)
利用ascii判断是否需要解码,需要的话直接转化回去

C++代码

#include<iostream>

using namespace std;
const int maxn = 1e5+100;
const char m[26] = {'V', 'W', 'X', 'Y','Z','A', 'B', 'C', 'D', 'E', 'F','G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O','P', 'Q', 'R', 'S', 'T','U'};
int main(){
	string ele;
	getline(cin, ele);
	for(int i=0;i<ele.length();i++){
		if(ele[i] >= 'A' && ele[i]<= 'Z')
			ele[i] = m[ele[i] - 'A'];
	}
	cout<<ele<<endl;
	return 0;
} 

必做题11-4

题目

题目
input&&output
input&&output
Sample

    #Input
    7
    2 2 2 1 1 2 2
    #Output
    4
    #Input
    6
    1 2 1 2 1 2
    #Output
    2
    #Input
    9
    2 2 1 1 1 2 2 2 2
    #Output
    6

题解

两个条件 连续 相等
因此我们只要连续计算 1的个数 和 2的个数
当出现变化时(0->1 1->0)若 1、2个数均非零(都有)则取二者较小值

C++代码

#include<iostream>

using namespace std;
const int maxn = 1e5+100;
int ele[maxn];
int main(){
	int n,num[3],ans = 0;
	num[1] = 0,num[2] = 0;
	cin>>n;
	for(int i=0;i<n;i++) ele[n] = 0; 
	for(int i=0;i<n;i++) cin>>ele[i];
	for(int i=0;i<n;i++){
		num[ele[i]]++;
		//cout<<i<<" : "<<ans<<" : "<<num[1]<<" : "<<num[2]<<endl;
		if(i!=n-1 && ele[i] != ele[i+1]){
			if(num[1]!=0&&num[2]!=0){
				if(min(num[1],num[2]) > ans) ans = min(num[1],num[2]);
				num[ele[i+1]] = 0;
			}
		}
		if(i==n-1 && min(num[1],num[2]) > ans) ans = min(num[1],num[2]);
	}
	cout<<2*ans<<endl;
}

选做题11-1 东东与 ATM

题目

题目
input&&output
input&&output
Sample

#input:
735 3  4 125  6 5  3 350
633 4  500 30  6 100  1 5  0 1
735 0
0 3  10 100  10 50  10 10
#output:
735
630
0
0

题解

本题仔细观察后发现是一道多重背包的问题,我们只需要把他抽象一下然后套用多重背包代码即可
多重背包
	1 二进制拆分:转化为0-1背包  (如 111(7) 拆为 100 010 001 6拆为 001 010  3
	2 执行0-1背包(此处还利用了滚动数组简化代码)
	(当前容量的最大价值为 (若当前物品容量小于当前背包容量)减去当前物品所占容量的价值+当前物品价值与当前价值的较大值

C++代码

#include<iostream>
//多重背包 
using namespace std;
const int maxn = 1e5+100;
int Cash,N;
long long sum;
int num[maxn],val[maxn];
int vv[maxn];
int f[maxn];

int main(){
	while(cin>>Cash>>N){
		for(int i=0;i<=Cash;i++) f[i] = 0;
		for(int i=1;i<=N;i++) cin>>num[i]>>val[i];
		//二进制拆分 
		int cnt=0;//拆分组数  vv拆分后的价值 
		for(int i=1;i<=N;++i){
			int t=num[i];
			for(int k=1;k<=t;k<<=1){
				vv[++cnt]=k*val[i];
				t-=k;
			}
			if(t>0)
				vv[++cnt]=t*val[i];
		}
		//0-1背包
		for(int i=1;i<=cnt;i++)
			for(int j=Cash;j>0;j--){
				if(j-vv[i] >= 0) f[j] = max(f[j],f[j-vv[i]] + vv[i]); 
			}
		cout<<f[Cash]<<endl;
	}
	return 0;
}

F - 选做题11-2 东东开车了

题目

题目
input&&output
input&&output
Sample

#input:
5 3 1 3 4
10 4 9 8 4 2
20 4 10 5 7 4
90 8 10 23 1 2 3 4 5 7
45 8 4 10 44 43 12 9 8 2
#output:
1 4 sum:5
8 2 sum:10
10 5 4 sum:19
10 23 1 2 3 4 5 7 sum:55
4 10 12 9 8 2 sum:45

题解

1.背包问题
N即为背包容量  M即为物品价值  time即为物品所占容量
本题需要输出具体的使用了哪些物品,我们只需要回溯过程,判断物品是否被放入过背包
由于本题多解 所以我们不需要关注顺序等

C++代码

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e5;
int card[25];
int f[25][maxn];
int main(){
	int n,m;//n 容量  m 物品 
	while(cin>>n){
		cin>>m;
		for(int i=1;i<=m;i++) card[i] = 0;
		for(int i=1;i<=m;i++){
			cin>>card[i];
		}
		for(int i=0;i<=m;i++) f[0][i] = 0;
		for(int i=1;i<=m;i++)
			for(int j=0;j<=n;j++){
				f[i][j]=f[i-1][j];
				if(j-card[i]>=0)//可以放 
					f[i][j] = max(f[i][j],f[i-1][j-card[i]] + card[i]);
			}
		int i=m,j=n;
		while(i>=1&&j>=0){//至少取一件  容量大于等于0 
			if(f[i][j] == f[i-1][j]) i--;//不放
			else{
				if(f[i][j] == f[i-1][j-card[i]] + card[i]){
					cout<<card[i]<<" ";
					j-=card[i--];
				}
			}
		}
		cout<<"sum:"<<f[m][n]<<endl;
	}
	return 0;
}
### 关于山东大学程序设计 Week5 的课程资料作业 尽管当前提供的引用并未直接提及山东大学程序设计思维实践的第5周具体内容,但从已有参考资料来看,可以推测该课程可能涉及的内容范围以及学习目标。 通常情况下,在类似的程序设计课程中,第五周的学习重点可能围绕以下几个方面展开: #### 可能的主题方向 1. **动态规划基础** 动态规划是一种解决多阶段决策过程最优化问题的方法。它通过将复杂问题分解成更简单的子问题来求解最优解[^2]。如果 Week5 涉及此主题,学生可能会接触到经典的动态规划问题,例如背包问题、最长公共子序列(LCS)、矩阵链乘法等。 2. **贪心算法的应用** 贪心算法的核心在于每一步都做出局部最优的选择,期望最终达到全局最优解。这种策略适用于某些特定场景下的问题,比如活动选择问题、霍夫曼编码等问题[^1]。 3. **图论初步** 图论作为离散数学的重要分支之一,在计算机科学中有广泛的应用价值。Week5 也可能引入基本概念如连通性检测、最小生成树(Kruskal 和 Prim 算法),或者单源最短路径(Dijkstra 算法)[^4]。 4. **高级数据结构介绍** 高级的数据结构能够显著提升解决问题效率。例如堆(Heap)用于实现优先队列;并查集(Union-Find Set)用来处理集合合并操作等等[^3]。 以下是基于上述假设整理的一道典型练习题及其解答思路: --- #### 练习题示例:最大连续子数组和 给定一个整数数组 `nums` ,找到其中具有最大和的一个连续子数组,并返回其总和。 ##### 思路分析: 采用 Kadane's Algorithm 来高效完成任务。核心思想是在遍历过程中维护两个变量——当前的最大子数组结束位置处的累加值(`current_sum`)以及迄今为止发现的整体最大值(`max_so_far`)。每当遇到新的元素时更新这两个量即可得出答案。 ```python def maxSubArray(nums): current_sum = nums[0] max_so_far = nums[0] for i in range(1, len(nums)): # 判断是否应该重新开始一个新的子数组还是延续之前的 current_sum = max(nums[i], current_sum + nums[i]) # 更新整体最大值 max_so_far = max(max_so_far, current_sum) return max_so_far ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值