SDU程序设计思维与实践作业Week11
必做题11-1
题目
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
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
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
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
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
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;
}