开始: 2022-10-15 19:30:00

2022CSP-J模拟赛1

结束: 2022-10-15 23:00:00
当前: 2025-0606-1919 04:13:33  类型:OI 状态:已经结束 

A-数字反转

这道题比较简单,不多赘述。注意判断负号、前导0以及单独一个0的情况。

#include <bits/stdc++.h>

using namespace std;

char a[1110000];

int l;

int main()

{

scanf("%s",a);

l=strlen(a);

while(a[l-1]=='0'&&l>1) l--;//去除前导0 同时注意只有一个0的情况

if(a[0]!='-') for(int i=l-1;i>=0;i--) printf("%c",a[i]); //如果不是负数 直接倒着输出即可

else //如果是负数 先输出负号再倒着输出

{

printf("-");

for(int i=l-1;i>=1;i--) printf("%c",a[i]);

}

return 0;

}
 

B-统计单词数

首先输入两个字符串a,b,然后把单词a放入字符串b中依次匹配。匹配之前,要将所有字符统一转成大写或小写。

变量t记录当前字符串a匹配到的位置,如果a[t]与当前枚举到的字符串b中的字符不同,就说明匹配失败,t重新归为0;

如果相同,则需要判断此时t是否为0,如果是0的话,证明此时是单词的开始,所以需要保证b[i-1]为空格,防止出现从半路开始匹配的情况,如单词to匹配到了onto;如果t不为0或t为0且b[i-1]为空格,则成功匹配,t++。

如果t++之后发现t已经等于字符串a的长度,就证明已经匹配上了,但此时还不能更新答案,还需要判断b[i+1]是否为空格,如果是空格才能累积答案,防止出现love和lover匹配的情况。

#include <bits/stdc++.h>

using namespace std;

string a,b;

int t=0,first=-1,ans=0;

int main()

{

getline(cin,a);

getline(cin,b);

//getline函数碰到空格不会停止

int la=a.length(),lb=b.length();

for(int i=0; i<la; i++) a[i]=tolower(a[i]);

for(int i=0; i<lb; i++) b[i]=tolower(b[i]);

//使用tolower函数实现大小写转换

for(int i=0; i<lb; i++)

{

if(a[t]!=b[i])//如果当前这个字母没有匹配上,回到起点

{

t=0;

continue;

}

if(t==0&&i!=0&&b[i-1]!=' ') continue;//如果正在匹配第一个字母,就要确定此时是不是一个单词的开始,如果不是就要跳过

//这一行代码时为了防止出现用to匹配onto类似的情况

t++; //当前字母匹配成功,t++匹配下一个字母

if(t==la)

{

//a字符串已经匹配完成,还要判断当前是不是一个单词的末尾

if(b[i+1]==' ')

{

ans++;

t=0;

if(ans==1) first=i-la+1;

//记录这个单词的首字母第一次出现的位置,即用当前所在位置减去单词的长度再加一

}

else t=0;

}

}

if(first==-1) printf("-1");//first==-1表明没有找到过这个单词

else printf("%d %d",ans,first);

return 0;

}

C-考前抱佛脚

思路:搜索

每道题有放在左脑和放在右脑两种选择,暴力枚举每道题是放在左脑还是右脑,使用递归的方法把所有可能性都枚举出来取最小值。

核心代码如下:

void dfs(int q,int x)

{

if(l>=minn||r>=minn) return;

if(x>a[q])

{

minn=min(minn,max(l,r));

return;

}

l+=s[q][x]; dfs(q,x+1); l-=s[q][x];

r+=s[q][x]; dfs(q,x+1); r-=s[q][x];

}

现在是第q科的第x道题,做这道题需要花费的时间为s[q][x],q这一科一共有a[q]道题。那么我们从第一道题开始选择把这道题放在左脑还是右脑,根据选择去修改l和r的值。当x==a[q]+1时 就表明这a[q]道题已经全部选完了,需要更新答案即minn。

函数的第一行为一个剪枝,如果左脑或者右脑当前的答案已经大于已知最优解,就没比较继续搜下去了,因为继续搜到最后也不可能得到更好的答案。

#include<bits/stdc++.h>

using namespace std;

int l,r,ans,minn;

int a[5];

int s[5][21];

void dfs(int q,int x)

{

if(l>=minn||r>=minn) return;

if(x>a[q])

{

minn=min(minn,max(l,r));

return;

}

l+=s[q][x]; dfs(q,x+1); l-=s[q][x];

r+=s[q][x]; dfs(q,x+1); r-=s[q][x];

}

int main()

{

scanf("%d%d%d%d",&a[1],&a[2],&a[3],&a[4]);

for(int i=1;i<=a[1];i++) scanf("%d",&s[1][i]); l=r=0; minn=1234567890; dfs(1,1); ans+=minn;

for(int i=1;i<=a[2];i++) scanf("%d",&s[2][i]); l=r=0; minn=1234567890; dfs(2,1); ans+=minn;

for(int i=1;i<=a[3];i++) scanf("%d",&s[3][i]); l=r=0; minn=1234567890; dfs(3,1); ans+=minn;

for(int i=1;i<=a[4];i++) scanf("%d",&s[4][i]); l=r=0; minn=1234567890; dfs(4,1); ans+=minn;

printf("%d",ans);

return 0;

}

D-两只牛

暴力模拟题,题目本身难度不大,但需要一定的代码熟练度。

我们需要的信息是约翰的坐标、约翰的方向、奶牛的坐标、奶牛的方向。每分钟我们做出的操作是:判断向前走一步是否是障碍,如果是,改变方向;如果不是,向前走一步。这一分钟的最末端我们判断约翰和奶牛是否相遇,如果相遇,程序结束;如果没有相遇,继续这个过程。

方向问题很好解决,用0,1,2,3分别表示四个方向即可,然后用一个方向数组来表示朝这个方向走一步的坐标变化。每次改变方向时只需要把方向变量+1,再对4取模即可。

最大的问题是怎么判断永远不会相遇。其实也很简单,思路和我们以前搜索时建立book数组类似,但这里的book数组要复杂一些。我们可以建立一个六维数组(不要被数组的维数吓到),表示约翰在这个坐标和这个方向上,奶牛在这个坐标和这个方向上,这样的状态我们已经走过。如果下一次再走到这个状态就表示陷入死循环了,永远无法相遇。

#include<bits/stdc++.h>

using namespace std;

const int dx[4]={-1,0,1,0};//上、右、下、左四个方向

const int dy[4]={0,1,0,-1};

int cx,cy,ct;//记录奶牛的坐标和方向

int fx,fy,ft;//记录约翰的坐标和方向

bool f[21][21],v[21][21][4][21][21][4];//f表示地图是否能走,v表示这种情况是否有出现过

void search()

{

int k=0;//当前分钟数

while(1)

{

if(cx==fx && cy==fy)//如果抓到了牛

{

printf("%d\n",k);//输出

exit(0);

}

if(v[fx][fy][ft][cx][cy][ct])//如果这种情况出现过 证明进入死循环

{

printf("0\n");

exit(0);

}

v[fx][fy][ft][cx][cy][ct]=1;//把这种情况设置为出现过

//找奶牛的方向

if(f[cx+dx[ct]][cy+dy[ct]]==false)//如果这个方向不能走

{

ct++;

ct%=4;

}

else cx=cx+dx[ct],cy=cy+dy[ct];//如果可以走就走

//找john的方向

if(f[fx+dx[ft]][fy+dy[ft]]==false)

{

ft++;

ft%=4;

}

else fx=fx+dx[ft],fy=fy+dy[ft];

k++;

}

}

int main()

{

char st[21];

//一开始f数组均为false 现在把能走的地方确定

for(int i=1;i<=10;i++)

{

scanf("%s",st+1);//输入

for(int j=1;j<=10;j++)

{

if(st[j]=='.') f[i][j]=true;//如果能走

if(st[j]=='F') fx=i,fy=j,f[i][j]=true;//如果是john

if(st[j]=='C') cx=i,cy=j,f[i][j]=true;//如果是牛

}

}

ct=ft=0;//一开始是向上

search();//开始搜索

return 0;

}