今天都在洛谷刷题
题目描述
有一个 n \times mn×m 的棋盘,在某个点 (x, y)(x,y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。
输入格式
输入只有一行四个整数,分别为 n, m, x, yn,m,x,y。
输出格式
一个 n \times mn×m 的矩阵,代表马到达某个点最少要走几步(左对齐,宽 55 格,不能到达则输出 -1−1)。
输入输出样例
输入 #1复制
3 3 1 1输出 #1复制
0 3 2 3 -1 1 2 1 4说明/提示
数据规模与约定
对于全部的测试点,保证 1 \leq x \leq n \leq 4001≤x≤n≤400,1 \leq y \leq m \leq 4001≤y≤m≤400。
这题用bfs,和迷宫最短路径很像,首先马走的方向有八个,需要定义一个结构体,弄一个队列,记录走到位置的步数,还要一个数组标记是否走过。
#include<stdio.h>
struct node
{
int x,y;
int s;//步数
}que[160001];
//int fx=3,fy=3;
int M[8][2]={-2,-1,-2,1,-1,-2,-1,2,1,-2,1,2,2,-1,2,1};//八个方向
int map[1000][1000];
int book[1000][1000]={0};//标记走没走过
int nx,ny,sx,sy,n,m;
int head=1,tail=1;
void bfs()
{
while(head<tail){
for(int i=0;i<8;i++){
nx=que[head].x+M[i][0];
ny=que[head].y+M[i][1];
if(nx<=0||ny<=0||nx>n||ny>m||book[nx][ny]==1)//不符合要求就继续搜下一个
continue;
if(book[nx][ny]==0){
// printf("%d %d\n",nx,ny);
book[nx][ny]=1;//标记已经走过
que[tail].x=nx;
que[tail].y=ny;
que[tail].s=que[head].s+1;//记录步数
map[nx][ny]=que[tail].s;//标记走到这需要多少步
tail++;
}
}
head++;
}
}
int main()
{
scanf("%d%d%d%d",&n,&m,&sx,&sy);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
map[i][j]=-1;
que[tail].x=sx;
que[tail].y=sy;
que[tail].s=0;
map[sx][sy]=que[tail].s;
book[sx][sy]=1;
tail++;
bfs();
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
printf("%-5d",map[i][j]);
printf("\n");
}
}
题目描述
给一n \times nn×n的字母方阵,内可能蕴含多个“
yizhong
”单词。单词在方阵中是沿着同一方向连续摆放的。摆放可沿着 88 个方向的任一方向,同一单词摆放时不再改变方向,单词与单词之间可以交叉,因此有可能共用字母。输出时,将不是单词的字母用*
代替,以突出显示单词。例如:输入: 8 输出: qyizhong *yizhong gydthkjy gy****** nwidghji n*i***** orbzsfgz o**z**** hhgrhwth h***h*** zzzzzozo z****o** iwdfrgng i*****n* yyyygggg y******g
输入格式
第一行输入一个数nn。(7 \le n \le 1007≤n≤100)。
第二行开始输入n \times nn×n的字母矩阵。
输出格式
突出显示单词的n \times nn×n矩阵。
输入输出样例
输入 #1复制
7 aaaaaaa aaaaaaa aaaaaaa aaaaaaa aaaaaaa aaaaaaa aaaaaaa输出 #1复制
******* ******* ******* ******* ******* ******* *******输入 #2复制
8 qyizhong gydthkjy nwidghji orbzsfgz hhgrhwth zzzzzozo iwdfrgng yyyygggg输出 #2复制
*yizhong gy****** n*i***** o**z**** h***h*** z****o** i*****n* y******g
这题就是一条路走到黑,看它是否符合字符要求。我们可以先判断一个方向的前两个字符是否符合要求,然后再从这一个方向判断剩下的字符。在判断这一个方向的同时,用两个数组v1,v2来记录位置,好到时候来标记那一串单词的位置。
#include<stdio.h>
int n;
int v1[10],v2[10];
char map[200][200];
int book[200][200]={0};//标记是否连成一个单词
char word[10]="yizhong";
void dfs(int x,int y,int k1,int k2,int s)
{
if(s==7){
for(int i=0;i<7;i++)
book[v1[i]][v2[i]]=1;//标记这一条
//printf("%d %d\n",x,y);
}
if(map[x][y]==word[s]&&x>=0&&y>=0&&x<n&&y<n)
{
v1[s]=x;v2[s]=y;
dfs(x+k1,y+k2,k1,k2,s+1);
}
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%s",&map[i]);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(map[i][j]=='y'){
for(int k1=-1;k1<2;k1++){
for(int k2=-1;k2<2;k2++){
if(map[i+k1][j+k2]=='i'){
dfs(i,j,k1,k2,0);//如果有一个方向的两个字符都对上了,就去判断这一条的字符
}
}
}
}
}
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(book[i][j]==0) printf("*");
else printf("%c",map[i][j]);
}
printf("\n");
}
}
题目描述
呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第ii层楼(1 \le i \le N)(1≤i≤N)上有一个数字K_i(0 \le K_i \le N)Ki(0≤Ki≤N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3, 3 ,1 ,2 ,53,3,1,2,5代表了K_i(K_1=3,K_2=3,…)Ki(K1=3,K2=3,…),从11楼开始。在11楼,按“上”可以到44楼,按“下”是不起作用的,因为没有-2−2楼。那么,从AA楼到BB楼至少要按几次按钮呢?
输入格式
共二行。
第一行为33个用空格隔开的正整数,表示N,A,B(1≤N≤200, 1≤A,B≤N)N,A,B(1≤N≤200,1≤A,B≤N)。
第二行为NN个用空格隔开的非负整数,表示K_iKi。
输出格式
一行,即最少按键次数,若无法到达,则输出-1−1。
输入输出样例
输入 #1复制
5 1 5 3 3 1 2 5输出 #1复制
3
用BFS不知道为啥一直AC90,然后我就用了DFS。说实话一开始没怎么看懂题目。
思路:因为只能上下移动,所以要判断他到的下一层到底存不存在或者走没走过。每搜完后一次到底后并且能到B楼,可设置一个参数sum用来比较它是否使用的次数最短的。
#include<stdio.h>
int N,A,B,ni;
int K[1000];
int M[2]={1,-1};
int book[1000]={0};
int sum=9999999;
void dfs(int i,int s)
{
if(i==B){
if(sum>s) sum=s;
return;
}
else if(s<=sum){
book[i]=1;
if(i+K[i]<=N&&book[i+K[i]]==0) dfs(i+K[i],s+1);
if(i-K[i]>0&&book[i-K[i]]==0) dfs(i-K[i],s+1);
book[i]=0;
}
}
int main()
{
scanf("%d%d%d",&N,&A,&B);
for(int q=1;q<=N;q++)
scanf("%d",&K[q]);
book[A]=1;
dfs(A,0);
if(sum==9999999) printf("-1\n");
else printf("%d\n",sum);
}