A - 必做题11-1
问题描述:
蒜头君从现在开始工作,年薪 N 万。他希望在蒜厂附近买一套 60 平米的房子,现在价格是 200 万。假设房子价格以每年百分之 K 增长,并且蒜头君未来年薪不变,且不吃不喝,不用交税,每年所得 N 万全都积攒起来,问第几年能够买下这套房子?(第一年年薪 N 万,房价 200
万)
输入格式
一行,包含两个正整数 N(10≤N≤50)
,K(1≤K≤20)
,中间用单个空格隔开。
输出格式
如果在第 20
年或者之前就能买下这套房子,则输出一个整数 M,表示最早需要在第 M
年能买下;否则输出"Impossible"。
Sample Input
50 10
Sample Output
8
思路:
很简单的数学问题
#include<iostream>
#include<math.h>
using namespace std;
double N,K;
int main()
{
cin>>N>>K;
double N1=(double)N;
double re=200;
double x=1+K/100;
for(long long int i=2;i<=20;i++)
{
re=re*x;
N=N+N1;
//cout<<N<<" "<<re<<" "<<x<<endl;
if(N>=re)
{
cout<<i<<endl;
return 0;
}
}
cout<<"Impossible"<<endl;
}
B - 必做题11-2
问题描述:
蒜头君的班级里有 n2 个同学,现在全班同学已经排列成一个 n∗n
的方阵,但是老师却临时给出了一组新的列队方案
为了方便列队,所以老师只关注这个方阵中同学的性别,不看具体的人是谁
这里我们用 0
表示男生,用 1
表示女生
现在蒜头君告诉你同学们已经排好的方阵是什么样的,再告诉你老师希望的方阵是什么样的
他想知道同学们已经列好的方阵能否通过顺时针旋转变成老师希望的方阵
不需要旋转则输出 0
顺时针旋转 90° 则输出 1
顺时针旋转 180° 则输出 2
顺时针旋转 270° 则输出 3
若不满足以上四种情况则输出 −1
若满足多种情况,则输出较小的数字
输入格式
第一行为一个整数 n
接下来的 n
行同学们已经列好的 01
方阵;
再接下来的 n
行表示老师希望的的 01
方阵。
输出格式
输出仅有一行,该行只有一个整数,如题所示。
数据范围
对于 100%
的数据中,1≤n≤20
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
思路:
输入数据之后对四种状况进行判断是不动,还是旋转,若有一种符合就输出并退出循环,若都不行就输出-1
#include<iostream>
using namespace std;
int n,A[30][30],B[30][30],C[20][20],D[20][20];
int judge(int x)
{
for(int i=0;i<n;i++)
{
for(int k=0;k<n;k++)
{
if(x==0)C[i][k]=A[i][k];
else if(x==1)C[i][k]=A[n-k-1][i];
else if(x==2)C[i][k]=A[n-i-1][n-k-1];
else if(x==3)C[i][k]=A[k][n-i-1];
}
}
/*cout<<endl<<endl;
cout<<"begin"<<endl;
for(int i=0;i<n;i++)
{
for(int k=0;k<n;k++)
{
cout<<C[i][k]<<" ";
}
cout<<endl;
}
cout<<"end"<<endl;*/
bool re=true;
for(int i=0;i<n;i++)
{
for(int k=0;k<n;k++)
{
if(C[i][k]!=B[i][k])re=false;
}
}
if(re)return x;
else return -1;
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
for(int k=0;k<n;k++)
{
cin>>A[i][k];
}
}
for(int i=0;i<n;i++)
{
for(int k=0;k<n;k++)
{
cin>>B[i][k];
}
}
int result=-1;
for(int i=0;i<4;i++)
{
result=judge(i);
if(result!=-1)break;
}
cout<<result<<endl;
}
C - 必做题11-3
问题描述:
Julius Caesar 曾经使用过一种很简单的密码。对于明文中的每个字符,将它用它字母表中后 5
位对应的字符来代替,这样就得到了密文。比如字符’A’用’F’来代替。如下是密文和明文中字符的对应关系。
密文A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
明文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
你的任务是对给定的密文进行解密得到明文。
你需要注意的是,密文中出现的字母都是大写字母。密文中也包括非字母的字符,对这些字符不用进行解码。
输入格式
一行,给出密文,密文不为空,而且其中的字符数不超过 200
。
输出格式
输出一行,即密文对应的明文。
Sample Input
NS BFW, JAJSYX TK NRUTWYFSHJ FWJ YMJ WJXZQY TK YWNANFQ HFZXJX
Sample Output
IN WAR, EVENTS OF IMPORTANCE ARE THE RESULT OF TRIVIAL CAUSES
思路:
用getline函数获取当前的数据,之后处理就非常简单了
#include<iostream>
using namespace std;
string A;
int main()
{
getline(cin,A);
int n=A.length();
for(int i=0;i<n;i++)
{
if('A'<=A[i]&&A[i]<='Z')
{
if('A'<=A[i]&&A[i]<='E')A[i]='V'+A[i]-'A';
else A[i]=A[i]-5;
cout<<A[i];
}
else cout<<A[i];
}
}
D - 必做题11-4
问题描述:
东东和他的女朋友(幻想的)去寿司店吃晚餐(在梦中),他发现了一个有趣的事情,这家餐厅提供的 n 个的寿司被连续的放置在桌子上 (有序),东东可以选择一段连续的寿司来吃
东东想吃鳗鱼,但是东妹想吃金枪鱼。核 平 起 见,他们想选择一段连续的寿司(这段寿司必须满足金枪鱼的数量等于鳗鱼的数量,且前一半全是一种,后一半全是另外一种)我们用1代表鳗鱼,2代表金枪鱼。
比如,[2,2,2,1,1,1]这段序列是合法的,[1,2,1,2,1,2]是非法的。因为它不满足第二个要求。
东东希望你能帮助他找到最长的一段合法寿司,以便自己能吃饱。
Input
输入:
第一行:一个整数n(2≤n≤100000),寿司序列的长度。
第二行:n个整数(每个整数不是1就是2,意义如上所述)
Output
输出:一个整数(代表东东可以选择的最长的一段连续的且合法的寿司)
Examples
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
思路:
先判断一下是否全部相等,若是直接输出0,若不是则break跳出循环,用vis和ans来存储当前段的2和1的个数,每一段的长度就是这两个值中较小值的两倍,maxm存储最大值。
#include<iostream>
using namespace std;
int A[100010],n;
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>A[i];
}
for(int i=0;i<n-1;i++)
{
if(A[i]==A[i+1])
{
if(i==n-2)
{
cout<<"0"<<endl;return 0;
continue;
}
}
else break;
}
int vis=0,ans=0,maxm=0,k=0;
for(int i=0;i<n;i++)
{
if(i>0&&A[i]!=A[i-1])k++;
if(k==2)
{
int l=min(vis,ans)*2;
maxm=max(maxm,l);
if(A[i-1]==2)vis=0;
else ans=0;
k=1;
}
if(A[i]==2)ans++;
else vis++;
}
int l=min(vis,ans)*2;
maxm=max(maxm,l);
cout<<maxm<<endl;
return 0;
}
E - 选做题11-1 东东与 ATM
问题描述:
一家银行计划安装一台用于提取现金的机器。
机器能够按要求的现金量发送适当的账单。
机器使用正好N种不同的面额钞票,例如D_k,k = 1,2,…,N,并且对于每种面额D_k,机器都有n_k张钞票。
例如,
N = 3,
n_1 = 10,D_1 = 100,
n_2 = 4,D_2 = 50,
n_3 = 5,D_3 = 10
表示机器有10张面额为100的钞票、4张面额为50的钞票、5张面额为10的钞票。
东东在写一个 ATM 的程序,可根据具体金额请求机器交付现金。
注意,这个程序计算程序得出的最大现金少于或等于可以根据设备的可用票据供应有效交付的现金。
Input
程序输入来自标准输入。 输入中的每个数据集代表特定交易,其格式为:Cash N n1 D1 n2 D2 ... nN DN其中0 <= Cash <= 100000是所请求的现金量,0 <= N <= 10是 纸币面额的数量,0 <= nk <= 1000是Dk面额的可用纸币的数量,1 <= Dk <= 1000,k = 1,N。 输入中的数字之间可以自由出现空格。 输入数据正确。
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
Sample Output
735
630
0
0
Hint
第一个数据集指定一笔交易,其中请求的现金金额为 735。 机器包含3种面额的纸币:4张钞票 125、6张钞票 5和3张钞票 350。 机器可以交付所需现金的确切金额。
在第二种情况下,机器的票据供应不能满足所要求的确切现金数量。 可以交付的最大现金为 630。 请注意,在机器中组合钞票以匹配交付的现金有多种可能性。
在第三种情况下,机器是空的,没有现金交付。 在第四种情况下,请求的现金金额为 0,因此机器不交付现金。
思路:
这道题是多重背包,钱币的总数为容量,不同的钱为不同的物品。
还用的二进制拆分的方法,把钱币拆分成不同的面值,转化为01背包问题,然后进行解题。
#include<iostream>
#include<string.h>
using namespace std;
int n,cash,A[20],B[20],C[100100],D[100100],f[100100];
int main()
{
while(cin>>cash)
{
cin>>n;
int vis=0;
memset(f,0,sizeof(f));memset(C,0,sizeof(C)),memset(D,0,sizeof(D));
for(int i=0;i<n;i++)
{
cin>>A[i]>>B[i];
//二进制拆分
for(int k=1;k<=A[i];k<<=1)
{
C[vis]=k*B[i];
D[vis++]=k*B[i];
A[i]=A[i]-k;
}
if(A[i]>0)
{
C[vis]=A[i]*B[i];
D[vis++]=A[i]*B[i];
}
}
for(int i=0;i<vis;i++)
{
for(int k=cash;k>=D[i];k--)
{
f[k]=max(f[k],f[k-D[i]]+C[i]);
}
}
cout<<f[cash]<<endl;
}
return 0;
}
F - 选做题11-2 东东开车
## 问题描述:
东东开车出去泡妞(在梦中),车内提供了 n 张CD唱片,已知东东开车的时间是 n 分钟,他该如何去选择唱片去消磨这无聊的时间呢
假设:
CD数量不超过20张
没有一张CD唱片超过 N 分钟
每张唱片只能听一次
唱片的播放长度为整数
N 也是整数
我们需要找到最能消磨时间的唱片数量,并按使用顺序输出答案(必须是听完唱片,不能有唱片没听完却到了下车时间的情况发生)
本题是 Special Judge
Input
多组输入
每行输入第一个数字N, 代表总时间,第二个数字 M 代表有 M 张唱片,后面紧跟 M 个数字,代表每张唱片的时长 例如样例一: N=5, M=3, 第一张唱片为 1 分钟, 第二张唱片 3 分钟, 第三张 4 分钟
所有数据均满足以下条件:
N≤10000
M≤20
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
Sample 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
思路:
这道题用了动态规划和基本的01背包问题。
此外还加了路径的输出问题,这也是本题比较难的一个点。
#include<iostream>
#include<string.h>
using namespace std;
int n,m,A[30],f[30][100100],vis[30],ans;
int main()
{
while(cin>>n)
{
cin>>m;
memset(A,0,sizeof(A));memset(vis,0,sizeof(vis));
for(int i=1;i<=m;i++)
{
cin>>A[i];
}
for(int i=0;i<=n;i++)
{
f[0][i]=0;
}
for(int i=1;i<=m;i++)
{
for(int k=0;k<=n;k++)
{
f[i][k]=f[i-1][k];
if(k>=A[i])
{
f[i][k]=max(f[i][k],f[i-1][k-A[i]]+A[i]);
}
}
}
ans=f[m][n];
int ff=0;
for(int i=m;i>=1;i--)
{
if(f[i][ans]>f[i-1][ans])
{
vis[ff++]=A[i];
ans=ans-A[i];
}
}
for(int i=ff-1;i>=0;i--)
{
cout<<vis[i]<<" ";
}
cout<<"sum:"<<f[m][n]<<endl;
}
}