寒假集训思维训练5题解
A - Full House 2
简单来说就是判断题,可以用讨论,也可以用数组来统计再枚举
#include<bits/stdc++.h>
using namespace std;
int vis[20];
int main() {
int x;
for(int i=1;i<=4;i++){
cin>>x;
vis[x]++;
}
//3 2 - > 3 1 2 2
for(int i=1;i<=13;i++){
for(int j=1;j<=13;j++){
if(i==j)continue;
if(vis[i]==3&&vis[j]==1||vis[i]==2&&vis[j]==2){
cout<<"Yes";return 0;
}
}
}
cout<<"No";
return 0;
}
B - Calculator
注意判断
00
00
00的情况就行了,如果是
00
00
00 记得要跳过一个0的位置。
#include<bits/stdc++.h>
using namespace std;
char s[1010];
int main() {
cin>>s+1;
int n=strlen(s+1);
int ans=0;
for(int i=1;i<=n;i++){
if(s[i]!='0')ans++;
else {
if(s[i+1]=='0'){
i++;
ans++;
}
else{
ans++;
}
}
}
cout<<ans;
return 0;
}
C - Operate 1
仔细想想,如果两个字符串长度的差大于等于2,那么一定无解
如果两个字符串长度一样,我们可以依次枚举每个位置的字符来检查,看看是否至多只有一个位置不一样,因为如果有一个位置不一样,我们可以修改。
如果
S
S
S的长度刚刚是
T
的长度
+
1
T的长度+1
T的长度+1 ,我们可以考虑S当中删除一个
假设
S
S
S字符串
[
1
到
l
e
n
]
[1到len]
[1到len] 我们还是去做匹配,当遇到一个位置
x
x
x满足
S
[
x
]
!
=
T
[
x
]
S[x]!=T[x]
S[x]!=T[x] 接下来考虑删除
S
[
x
]
S[x]
S[x] ,那么接下来就要由
S
[
x
+
1
]
去匹配
T
[
x
]
S[x+1]去匹配T[x]
S[x+1]去匹配T[x];
S
[
x
+
2
]
去匹配
T
[
x
+
1
]
S[x+2]去匹配T[x+1]
S[x+2]去匹配T[x+1];
S
[
x
+
3
]
去匹配
T
[
x
+
2
]
S[x+3]去匹配T[x+2]
S[x+3]去匹配T[x+2];以此类推,所以同学们只需要写另一个循环来枚举就行了。
如果S的长度比T短1,实际上插入我们是不好思考的,因为不知道在哪里插入。我们可以反向思考,S插入一个相当于T删除一个,那么问题变为 了检查T字符串删除一个 能不能变为S字符串,用上面的方法就行了
#include<bits/stdc++.h>
using namespace std;
char s[500010];
char t[500010];
int main() {
int k;
cin>>k;
cin>>s+1;
cin>>t+1;
int n=strlen(s+1);
int m=strlen(t+1);
if(abs(m-n)>1){
cout<<"No";
return 0;
}
if(n==m){
//长度一样但是字符串不一样
int op=0;//修改次数
for(int i=1;i<=n;i++){
if(s[i]!=t[i]){
op++;
}
}
if(op<=1){
cout<<"Yes";return 0;
}
else {
cout<<"No";return 0;
}
}
if(n==m+1){
//只能考虑删一个
int pos;
for(int i=1;i<=n;i++){
if(s[i]!=t[i]){
pos=i;break;
}
}
for(int i=pos+1,j=pos;i<=n;i++,j++){
if(s[i]!=t[j]){
cout<<"No";return 0;
}
}
cout<<"Yes";return 0;
}
if(n==m-1){
//只能考虑插入一个 等价于T串删除一个位置
int pos;
for(int i=1;i<=m;i++){
if(s[i]!=t[i]){
pos=i;break;
}
}
for(int i=pos+1,j=pos;i<=m;i++,j++){
if(s[j]!=t[i]){
cout<<"No";return 0;
}
}
cout<<"Yes";return 0;
}
return 0;
}
D - Equally
其实那么三个数一样,要么把两个小一点的放在一块,来检查。所以排序就行了
#include<bits/stdc++.h>
using namespace std;
int A[5];
int main() {
for(int i=1;i<=3;i++){
cin>>A[i];
}
sort(A+1,A+1+3);
if(A[1]==A[3]||A[1]+A[2]==A[3]){
cout<<"Yes";
}
else{
cout<< "No";
}
return 0;
}
E - Santa Claus 1
这个问题简单来说就是,你控制的人在
(
x
,
y
)
(x,y)
(x,y)位置,接下来有一系列指令
T
T
T字符串,你要按指令去走格子,吃糖果(我视为@ 是糖果,吃了之后修改为 . 点)
注意不要越界
#include<bits/stdc++.h>
using namespace std;
char s[110][110];
char T[10010];
int main() {
int n,m,x,y;
cin>>n>>m>>x>>y;
for(int i=1;i<=n;i++){
cin>>s[i]+1;
}
cin>>T+1;
int len=strlen(T+1);
int ans=0;
for(int i=1;i<=len;i++){
if(T[i]=='U'){
if(s[x-1][y]=='.'||s[x-1][y]=='@'){
x--;
if(s[x][y]=='@'){
ans++;
s[x][y]='.';
}
}
}
else if(T[i]=='D'){
if(s[x+1][y]=='.'||s[x+1][y]=='@'){
x++;
if(s[x][y]=='@'){
ans++;
s[x][y]='.';
}
}
}
if(T[i]=='L'){
if(s[x][y-1]=='.'||s[x][y-1]=='@'){
y--;
if(s[x][y]=='@'){
ans++;
s[x][y]='.';
}
}
}
if(T[i]=='R'){
if(s[x][y+1]=='.'||s[x][y+1]=='@'){
y++;
if(s[x][y]=='@'){
ans++;
s[x][y]='.';
}
}
}
}
cout<<x<<" "<<y<<" "<<ans;
return 0;
}
F - Illuminate Buildings
其实,我们可以来枚举从哪个灯开始,接下来依次枚举间隔,来检查最大值就行了
即我先枚举从第
i
i
i个灯开始,接下来
i
到
N
i到N
i到N的灯都有可能选,接下来枚举间隔
j
=
1
,
2
,
3...
(
n
−
i
)
j=1,2,3...(n-i)
j=1,2,3...(n−i)
来检查每间隔
j
j
j,是不是还是第
i
i
i个灯一样的灯 最后保留最大值
#include<bits/stdc++.h>
using namespace std;
const int N=3005;
int h[N];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++)cin>>h[i];
int ans=1;
for(int t=1;t<=n;t++){//暴力枚举间隔
for(int i=1;i<=t;i++){
int sum=0;
for(int j=i;j<=n;j+=t){
ans=max(ans,sum);
if(j==i||h[j]==h[j-t])sum++;
else sum=1;
ans=max(ans,sum);
}//求出最长的合法序列
}
}
cout<<ans<<"\n";
}
G题H题不讲了
I - Perfect Standings
题目是这样子的,一场比赛有
A
,
B
,
C
,
D
,
E
A,B,C,D,E
A,B,C,D,E五道题,每道题的分数给我们了
题目想让我们输出,在所有的解题情况当中,前31名的做题情况。
即先按做题得到的总分排序,如果总分一样的两个人,按做题的题目编号来排序,类似于如果小明做了ABC题得分 跟 小刚做了BCD题一样,那么按字典序来排序的话(字典序指的是,两个字符串从前往后做比较,谁第一次比另一个小了,谁的字典序就更小)。按字典序排序,应该先输出小明的做题情况ABC,再输出BCD。
所以这个题首先我们得记录所有可能的做题情况,即对于5道题目,所有的做题可能,都要枚举出来,存下来。
如何枚举5道题目的做题情况呢? 可以考虑0,1 其中0表示没做出来
具体枚举方式请看下面代码。我分别用
i
,
j
,
k
,
p
,
q
的值表示第
12345
道题目有没有解决
i,j,k,p,q的值表示第1 2 3 4 5道题目有没有解决
i,j,k,p,q的值表示第12345道题目有没有解决
然后来计算分数,统计到结构体里面,顺便记录一下这个人每道题的做题情况,即
A
[
i
]
=
1
表示第
i
个题做出来了
A[i]=1 表示第i个题做出来了
A[i]=1表示第i个题做出来了
#include<bits/stdc++.h>
using namespace std;
struct node{
int solve[6];
int fen;
}A[50];
int B[10];
bool cmp(node x,node y){
if(x.fen==y.fen){
for(int i=1;i<=5;i++){
if(x.solve[i]!=y.solve[i])return x.solve[i]>y.solve[i];
}
}
return x.fen>y.fen;
}
int main() {
for(int i=1;i<=32;i++){
for(int j=1;j<=5;j++){
A[i].solve[j]=0;
A[i].fen=0;
}
}
for(int i=1;i<=5;i++){
cin>>B[i];
}
int num=0;
for(int i=0;i<=1;i++){
for(int j=0;j<=1;j++){
for(int k=0;k<=1;k++){
for(int p=0;p<=1;p++){
for(int q=0;q<=1;q++){
num++;// num记录 哪一种做题情况
A[num].solve[1]=i;
A[num].solve[2]=j;
A[num].solve[3]=k;
A[num].solve[4]=p;
A[num].solve[5]=q;// solve[5] 表示第5个题的做题情况
for(int w=1;w<=5;w++){
A[num].fen+=B[w]*A[num].solve[w];//计算当前这个情况的总分
//B数组对应的是第w道题的分数
//solve[w] 对应第w道题 当前有没有做出来
//没做出来就是0去做乘法,所以拿不到这个题的分数
}
}
}
}
}
}
sort(A+1,A+1+33,cmp);// 排序 注意要写好排序函数 分数一样的情况
for(int i=1;i<=31;i++){ //输出前31名的做题情况
for(int j=1;j<=5;j++){// 枚举当前这个人做了哪些题,按字母输出
if(A[i].solve[j]==1){ //检查当前这个人 第j道题有没有做出来
cout<<char('A'+j-1);
}
}
cout<<'\n';
}
return 0;
}