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

必做题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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值