第一周搜索
B-Knight Moves
题目大意
给定一个骑士(马)在棋盘上的起点和终点,输出需要移动的最小步数。如果起始点和终点相同,则输出 0。
分析
BFS,向8种走位搜索,搜到就行了。
代码
#include<stdio.h>
#include<queue>
using namespace std;
/*
前两次wa是没有清空队列
*/
struct point
{
int x;
int y;
int step;
};
queue<point> r;
int cb[500][500],v[500][500];//chessboard 和 标记
int dx[10]={-2,-1,1,2,2,1,-1,-2};
int dy[10]={1,2,2,1,-1,-2,-2,-1};
int main(){
int n1,n,l;
int x1,y1,x2,y2;
scanf("%d",&n);
for(n1=0;n1<n;n1++){
scanf("%d",&l);
scanf("%d %d",&x1,&y1);
scanf("%d %d",&x2,&y2);
for(int i=0;i<l;i++)
for(int j=0;j<l;j++){
v[i][j] = 0;
}
point start;
start.x = x1;
start.y = y1;
start.step = 0;
r.push(start);
v[start.x][start.y] = 1;
//bfs
while(!r.empty()){
int x = r.front().x,y = r.front().y;
if(x==x2&&y==y2)
{
printf("%d\n",r.front().step);
break;
}
for(int k=0;k<8;k++){
int nx,ny;
nx = x + dx[k]; ny = y +dy[k];
if(nx>=0&&nx<l&&ny>=0&&ny<l&&v[nx][ny]==0){
point temp;
temp.x = nx;
temp.y = ny;
temp.step = r.front().step +1;
r.push(temp);
v[nx][ny] = 1;
}
}
r.pop();
}
while(!r.empty()) r.pop(); //清空队列
}
return 0;
}
C - Computer Game
题目大意
有两行n列的网格,每格要么是0,要么是1(0表示没障碍可以通过,1表示有障碍不可以通过。人物可以从()移动到,其中。判断能不能从移动到。
分析
如果有一列全是1,人物就无法突破1的阵列,输出NO。否则就输出YES。
代码
#include<stdio.h>
// 把字符数组写成数字数组了
int main(){
int i,n;
int flag;
scanf("%d",&n);
for(i=0;i<n;i++){
int j,m;
char a[200],b[200];
scanf("%d",&m);
flag =0;
getchar();
for(j=0;j<m;j++)
scanf("%c",&a[j]);
getchar();
for(j=0;j<m;j++)
scanf("%c",&b[j]);
for(j=0;j<m;j++){
if(a[j]=='1'&&b[j]=='1'){
flag = 1;
printf("NO\n");
break;
}
}
if(flag == 0)
printf("YES\n");
}
return 0;
}
D - 驾驶卡丁车
小Q正在设计一款2D卡丁车游戏,你的任务是帮助小Q实现其中的一部分功能。
在这款游戏中,游戏地图是一张 n 行 m 列的网格,从上到下依次编号为第 1 行到第 n 行,从左往右依次编号为第 1 列到第 m 列,其中第 i 行第 j 列的格子的坐标为 (i,j),每个格子要么是可以通行的平地,要么是不可通行的障碍。
在地图上的某个平地格子处有一辆由玩家操控的卡丁车。卡丁车的移动速率为 vv,并且一共有8种可能的朝向,分别为:
- "上":前进一步时,将从 (x,y) 移动到 (x−1,y)。
- "下":前进一步时,将从 (x,y) 移动到 (x+1,y)。
- "左":前进一步时,将从 (x,y) 移动到 (x,y−1)。
- "右":前进一步时,将从 (x,y) 移动到 (x,y+1)。
- "左上":前进一步时,将从 (x,y) 移动到 (x−1,y−1)。
- "右上":前进一步时,将从 (x,y) 移动到 (x−1,y+1)。
- "左下":前进一步时,将从 (x,y) 移动到 (x+1,y−1)。
- "右下":前进一步时,将从 (x,y) 移动到 (x+1,y+1)。
一开始卡丁车朝上位于某个平地格子处,其初始移动速率为 v=0。接下来玩家将依次输入 q 条操作指令,每条操作指令是下列中的一种:
- "L":卡丁车朝向往左转 45 度。
- "R":卡丁车朝向往右转 45 度。
- "U":卡丁车的速率由 v 增大至 v+1。
- "D":卡丁车的速率由 v* 减小至 max(v−1,0)。
在执行完每条操作指令后,卡丁车都会沿着其朝向前进 v 步,在移动结束后才会继续响应后续指令。在前进的过程中,如果某一步尝试驶入某个障碍格子或者尝试驶出地图,那么说明卡丁车发生了碰撞,它将就此结束移动,在保持朝向的同时速率 v 降低为 0。特别要注意的是,当朝向是斜45度时,为了防止"穿模"现象的发生,如果卡丁车两侧都是障碍,那么卡丁车同样将被认为发生了碰撞。例如卡丁车朝向右下,现在将从 (x,y) 移动到(x+1,y+1),那么如果 (x+1,y) 和(x,y+1) 都是障碍,则卡丁车发生了碰撞。
请写一个程序,在执行完每条操作指令后且卡丁车完成移动之后,汇报卡丁车的坐标以及这次移动过程中是否发生了碰撞。
题目大意
有一个n*m的地图,每个坐标可能是"#"(障碍), "."(平地), " * "(卡丁车)中的一种。接下来有q(1<q<500)条指令,输出每条指令后车的位置和是否撞墙了。
分析
模拟,设置一个移动和转弯的函数,依次读取命令执行即可。当速度大于1的时候,随时可能撞墙,我选择走一步看一下前面是不是墙。在向斜的方向上移动时,要判断是否穿墙,即额外判断车和下个位置形成的2*2的格子里的另外两个是不是都是墙。
我写烦了,可以搞个二维数组存八个方向的移动,然后把上下左右作一类讨论,其余方向做一类讨论。(
代码
#include<stdio.h>
char map[100][100]; //存地图
char ww[550]; //存命令
int v=0,k,k1; //0上 1右上 2右 。。。
void rush(int x,int y,int k,int d,int v){ //x y k d 方向 v 速度
if(k==0)
return ;
else{
if(ww[k1-k]=='U'){
v++;
}
else if(ww[k1-k]=='D'){
if(v>0) v--;
}
else if(ww[k1-k]=='R'){
d++;
if(d==8) d = 0;
}
else if(ww[k1-k]=='L'){
d--;
if(d==-1) d = 7;
}
int v2;
int flag=0;
if(v){
if(d==0){
for(v2=1;v2<=v;v2++){
if(map[x-v2][y]=='#'){
printf("Crash! %d %d\n",x-v2+1,y);
rush(x-v2+1,y,k-1,0,0);
flag =1;
break; //******************
}
}
if(flag==0) {
printf("%d %d\n",x-v,y);
rush(x-v,y,k-1,0,v);
}
}
else if(d==2){
for(v2=1;v2<=v;v2++){
if(map[x][y+v2]=='#'){
printf("Crash! %d %d\n",x,y+v2-1);
rush(x,y+v2-1,k-1,2,0);
flag =1;
break;
}
}
if(flag==0) {
printf("%d %d\n",x,y+v);
rush(x,y+v,k-1,2,v);
}
}
else if(d==4){
for(v2=1;v2<=v;v2++){
if(map[x+v2][y]=='#'){
printf("Crash! %d %d\n",x+v2-1,y);
rush(x+v2-1,y,k-1,4,0);
flag =1;
break;
}
}
if(flag==0) {
printf("%d %d\n",x+v,y);
rush(x+v,y,k-1,4,v);
}
}
else if(d==6){
for(v2=1;v2<=v;v2++){
if(map[x][y-v2]=='#'){
printf("Crash! %d %d\n",x,y-v2+1);
rush(x,y-v2+1,k-1,6,0);
flag =1;
break;
}
}
if(flag==0) {
printf("%d %d\n",x,y-v);
rush(x,y-v,k-1,6,v);
}
}
else if(d==1){
for(v2=1;v2<=v;v2++){
if(map[x-v2][y+v2]=='#'||(map[x-v2][y+v2-1]=='#'&&map[x-v2+1][y+v2]=='#')){
printf("Crash! %d %d\n",x-v2+1,y+v2-1);
rush(x-v2+1,y+v2-1,k-1,1,0);
flag =1;
break;
}
}
if(flag==0) {
printf("%d %d\n",x-v,y+v);
rush(x-v,y+v,k-1,1,v);
}
}
else if(d==7){
for(v2=1;v2<=v;v2++){
if(map[x-v2][y-v2]=='#'||(map[x-v2][y-v2+1]=='#'&&map[x-v2+1][y-v2]=='#')){
printf("Crash! %d %d\n",x-v2+1,y-v2+1);
rush(x-v2+1,y-v2+1,k-1,7,0);
flag =1;
break;
}
}
if(flag==0) {
printf("%d %d\n",x-v,y-v);
rush(x-v,y-v,k-1,7,v);
}
}
else if(d==5){
for(v2=1;v2<=v;v2++){
if(map[x+v2][y-v2]=='#'||(map[x+v2][y-v2+1]=='#'&&map[x+v2-1][y-v2]=='#')){
printf("Crash! %d %d\n",x+v2-1,y-v2+1);
rush(x+v2-1,y-v2+1,k-1,5,0);
flag =1;
break;
}
}
if(flag==0) {
printf("%d %d\n",x+v,y-v);
rush(x+v,y-v,k-1,5,v);
}
}
else if(d==3){
for(v2=1;v2<=v;v2++){
if(map[x+v2][y+v2]=='#'||(map[x+v2-1][y+v2]=='#'&&map[x+v2][y+v2-1]=='#')){
printf("Crash! %d %d\n",x+v2-1,y+v2-1);
rush(x+v2-1,y+v2-1,k-1,3,0);
flag =1;
break;
}
}
if(flag==0) {
printf("%d %d\n",x+v,y+v);
rush(x+v,y+v,k-1,3,v);
}
}
}
else{
printf("%d %d\n",x,y);
rush(x,y,k-1,d,v);
}
}
return ;
}
int main(){
int m,n,i,j;
scanf("%d %d",&m,&n);
//边界 1~m 1~n
for(i=0;i<=m+1;i++){
map[i][0]='#';
map[i][n+1]='#';
}
for(i=0;i<=n+1;i++){
map[0][i]='#';
map[m+1][i]='#';
}
//输入
getchar();
for(i=1;i<=m;i++){
for(j=1;j<=n;j++){
scanf("%c",&map[i][j]);
}
getchar();
}
int x1,y1;
// x1 , y1 定位
for(i=1;i<=m;i++){
for(j=1;j<=n;j++){
if(map[i][j]=='*'){
x1 = i ;
y1 = j ;
}
}
}
scanf("%d",&k);
k1 = k;
scanf("%s",ww);
rush(x1,y1,k,0,0);
return 0;
}
H - Prime Ring Problem
题目大意
输入n(0<n<16), 找出1~n组成的一个圆,要求圆上相邻的两个数之和要是素数,按1为首,一排数的格式输出。
分析
DFS+回溯,v[20]用来标记数是否用过,每用一个数标记一下,深搜结束取消标记,达到遍历的效果
大致就是从第二个数开始n-1个数全排列过一遍,符合相邻数相加是素数且最后一个数+1也是素数就输出。
代码
#include<stdio.h>
#include<math.h>
int v[20],num[20];
int isprime(int x,int y){
int z = x + y;
for(int i=2;i<=sqrt(z);i++){
if(z%i==0)
return 0;
}
return 1;
}
void dfs(int x,int n){ //x 代表第几个数
if(x==n&&isprime(1,num[n])){
for(int j = 1;j<n;j++)
printf("%d ",num[j]);
printf("%d",num[n]);
printf("\n");
}
else{
for(int i=2;i<=n;i++){
if(isprime(num[x],i)&&v[i]==0){
v[i] = 1;
num[x+1] = i;
dfs(x+1,n);
v[i] = 0;
}
}
}
}
int main(){
int n,k=1;
num[1] = 1;
while(scanf("%d",&n)!=EOF){
if(k!=1) printf("\n"); // 。。。
for(int i = 1;i<=n;i++)
v[i] = 0;
printf("Case %d:\n",k++);
dfs(1,n);
}
return 0;
}
J - 山峰和山谷 Ridges and Valleys
题目大意
一块八方相连高度相同的区域,比其相邻的区域都高即为山峰,都低则为山谷,数山峰和山谷的个数。
分析
对所有格子遍历,找到高度相同的一片区域并做上标记,比较其与相邻格子高度,一次bfs确定这次的区域是山峰还是山谷
把while(!r.empty()){
写成了if(!r.empty()){
看了好久没看出来
move 在编译时好像有冲突 PE了
代码
#include<stdio.h>
#include<queue>
using namespace std;
int n;
int a[1005][1005],v[1005][1005];
int up=0,down=0,feng,gu;
int mov[8][2]={{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};
struct ww{
int x;
int y;
int mark;
};
queue<ww> r;
void bfs(int x,int y,int t){
while(!r.empty()){
for(int i=0;i<8;i++){
int nx=r.front().x+mov[i][0],ny=r.front().y+mov[i][1];
if(nx>=0&&ny>=0&&nx<n&&ny<n){
if(a[nx][ny]==t&&v[nx][ny]==0){
ww temp;
temp.x = nx;
temp.y = ny;
temp.mark = t;
v[nx][ny] = 1;
r.push(temp);
}
if(a[nx][ny]>t){ //不是山峰
feng = 0;
}
if(a[nx][ny]<t){
gu = 0;
}
}
}
r.pop();
}
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
v[i][j]=0;
scanf("%d",&a[i][j]);
}
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(v[i][j]==0){
while(!r.empty()) r.pop();
v[i][j] = 1;
ww first;
first.x = i;
first.y = j;
first.mark = a[i][j];
r.push(first);
feng=1 ; gu = 1;
bfs(i,j,a[i][j]);
if(feng==1) up++;
if(gu==1) down++;
}
}
}
printf("%d %d",up,down);
return 0;
}
M - Protect Sheep
题目大意
在草场上有狼和羊,狼和羊相邻羊就会被吃掉,可以在草地上放狗阻挡狼吃羊,问是否能保护所有羊,能就输出一种可能性,不能就不能。
分析
只要狼和羊不相邻,就可以一圈狗把羊/狼围住,那肯定吃不着了。为了简化输出,可以把草全换成狗。
代码
#include<iostream>
using namespace std;
// L17 L18 为什么不能互换
char cc[505][505];
int main(){
int r,c;
scanf("%d %d",&r,&c);
int i,j,flag = 0;
for(i=1;i<=r;i++){
for(j=1;j<=c;j++){
cin >> cc[i][j];
}
}
for(i=1;i<=r;i++){
for(j=1;j<=c;j++){
if(cc[i][j]=='S'){
if(cc[i-1][j]=='W'||cc[i+1][j]=='W'||cc[i][j-1]=='W'||cc[i][j+1]=='W')
{
printf("No\n");
return 0;
}
}
}
}
printf("Yes\n");
for(i=1;i<=r;i++){
for(j=1;j<=c;j++){
if(cc[i][j]=='.')
printf("D");
else
printf("%c",cc[i][j]);
}
printf("\n");
}
return 0;
}
N - Maximum Product
题目大意
有n个数(n<18)形成一段序列,求连续子序列的最大乘积,都小于0就输出0
分析
求连续子序列的最大乘积,那就遍历每一种子序列求乘积,乘积最大可到,用long long 存最大值。
代码
#include<stdio.h>
int a[20];
int main(){
long long max,temp;
int N,i,j,l,t,k=0;
while(scanf("%d",&N)!=EOF){
max = 0;
k++;
for(i=0;i<N;i++)
scanf("%d",&a[i]);
for(i=0;i<N;i++){ //头
for(l=1;i+l<=N;l++){ //长度
temp = 1;
for(t=0;t<l;t++)
temp *=a[i+t];
if(temp>max)
max = temp;
}
}
printf("Case #%d: The maximum product is %lld.\n\n",k,max);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现