dfs,bfs,恐怖,但不恐怖的是……三道是洛谷原题,虽然断网,但第二题我做过 哈哈哈
———————————本来不想说废话的———————————
1.马的遍历
(horse.pas/c/cpp)
【问题描述】
有一个n*m的棋盘(1<n,m<=400),在某个点上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步
【输入】
一行四个数据,棋盘的大小和马的坐标
【输出】
一个n*m的矩阵,代表马到达某个点最少要走几步(不能到达则输出-1
每行的m个数用空格隔开
【输入输出样例1】
3 3 1 1 | 0 3 2 3 -1 1 2 1 4 |
不知道为什么scdn更新了,用着haob好不方便……
#include<bits/stdc++.h>
using namespace std;
inline const long long read() {
long long num=0,bj=1;char x=getchar();
while(x<'0'||x>'9') {if(x=='-')bj=-1;x=getchar();}
while(x>='0'&&x<='9') {num=num*10+x-'0';x=getchar();}
return num*bj;
}
long long n,m,x1,yy,ans[410][410];
const int tx[8]={2,1,-1,-2,-2,-1,1,2},ty[8]={1,2,2,1,-1,-2,-2,-1};
struct ss
{
int x,y;
};
ss work(int x,int y)
{
ss temp;
temp.x=x;
temp.y=y;
return temp;
}
void bfs()
{
int i,j;
queue<ss>q;
q.push(work(x1,yy));
while(!q.empty())
{
ss xian=q.front();
q.pop();
int a=xian.x,b=xian.y;
for(i=0;i<8;i++)
if(a+tx[i]>=1&&a+tx[i]<=n&&b+ty[i]>=1&&b+ty[i]<=m&&!ans[a+tx[i]][b+ty[i]])
if(a+tx[i]!=x1||b+ty[i]!=yy)
{
ans[a+tx[i]][b+ty[i]]=ans[a][b]+1;
q.push(work(a+tx[i],b+ty[i]));
}
}
}
int main()
{
freopen("horse.in","r",stdin);
freopen("horse.out","w",stdout);
int i,j;
n=read(),m=read(),x1=read(),yy=read();
for(bfs(),i=1;i<=n;i++)
{
for(j=1;j<m;j++)
{
if(!ans[i][j]&&(i!=x1||j!=yy))
printf("%d ",-1);
else printf("%d ",ans[i][j]);
}
if(!ans[i][m]&&(i!=x1||m!=yy))printf("%d\n",-1);
else printf("%d\n",ans[i][m]);
}
fclose(stdout);
fclose(stdin);
return 0;
}
注意好不要越界,用bfs搜索
二.中国象棋air
(chess.pas/c/cpp)
【问题描述】
这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法。大家肯定很清楚,在中国象棋中炮的行走方式是:一个炮攻击到另一个炮,当且仅当它们在同一行或同一列中,且它们之间恰好 有一个棋子。你也来和小可可一起锻炼一下思维吧!
【输入】
一行包含两个整数N,M,之间由一个空格隔开。
【输出】
总共的方案数
答案不超过int能容纳的最大值
【输入输出样例1】
1 3 | 7 |
【输入输出样例2】
3 2 | 49 |
【数据范围】
样例说明
除了3个格子里都塞满了炮以外,其它方案都是可行的,所以一共有2*2*2-1=7种方案。
数据范围
30% N=1
100% N,M<=6
其实这么小的数据,暴力搜索可以过的,但因为我是做过的……所以我还是选择再打一遍区间dp
#include<bits/stdc++.h>
using namespace std;
inline const long long read() {
long long num=0,bj=1;char x=getchar();
while(x<'0'||x>'9') {if(x=='-')bj=-1;x=getchar();}
while(x>='0'&&x<='9') {num=num*10+x-'0';x=getchar();}
return num*bj;
}
long long n,m,f[1020][1020][1020],ans=0;
int i,j,k;
int main()
{
freopen("chess.in","r",stdin);
freopen("chess.out","w",stdout);
n=read(),m=read();
for(f[0][0][0]=1,i=1;i<=n;i++)
for(j=0;j<=m;j++)
for(k=0;j+k<=m;k++)
{
f[i][j][k]+=f[i-1][j][k];
if(j)f[i][j][k]+=f[i-1][j-1][k]*(m-k-j+1);
if(k)f[i][j][k]+=f[i-1][j+1][k-1]*(j+1);
if(j>=2)f[i][j][k]+=f[i-1][j-2][k]*(m-j-k+2)*(m-j-k+1)/2;
if(k>=2) f[i][j][k]+=f[i-1][j+2][k-2]*(j+2)*(j+1)/2;
if(k)f[i][j][k]+=f[i-1][j][k-1]*(m-j-k+1)*j;
}
for(i=0;i<=m;i++)for(j=0;j<=m;j++)ans+=f[n][i][j];
printf("%d",ans);
fclose(stdout);
fclose(stdin);
return 0;
}
3.奇怪的机器人
(robot.pas/c/cpp)
【问题描述】
有一个奇怪的机器人,它被关在一个实验室里。
实验室是一个长方形,被分成了n行m列个格子,某些格子能走而有些不嫩
现在这个机器人每次能走到与他相邻的上下左右四个格子(如果相邻的格子能走的话),但是不同方向的花费不一样,往上,下,左,右四个方向走一次分别需要花费1,2,3,4块钱。
机器人在第x1行y1列的格子上,出口在x2行y2列的格子上,问你机器人想出去最少需要花多少钱?
【输入】
第一行两个用空格隔开的整数n和m
接下来n行,每行m个字符,表示地图
如果第i行j列个字符为’.’,表示这个地方能走,否则不能
最后一行四个用空格隔开的整数x1,y1,x2,y2
保证第x1行y1列和第x2行y2列一定是’.’
【输出】
一行一个整数,如果机器人能出去则为它最少需要花多少钱,否则为-1
【输入输出样例1】
4 4 .... .**. ..*. .... 3 2 3 3 | 11 |
【输入输出样例2】
1 3 .*. 1 1 1 3 | -1 |
【数据范围】
1<=n,m<=50
这题,一开始我错了,越界+少情况……
修改以后:
#include<bits/stdc++.h>
using namespace std;
inline const long long read() {
long long num=0,bj=1;char x=getchar();
while(x<'0'||x>'9') {if(x=='-')bj=-1;x=getchar();}
while(x>='0'&&x<='9') {num=num*10+x-'0';x=getchar();}
return num*bj;
}
int fx[4]={1,-1,0,0},fy[4]={0,0,1,-1},w[4]={2,1,4,3};
char s[510];
int l1,r1,l2,r2,f[510][510],q[510000],hd=0,n,m;
bool vis[510][510],a[510][510];
int work(int x,int y){return (x-1)*m+y-1;}
void bfs()
{
f[l1][r1]=0,hd=1;
q[hd]=work(l1,r1);
for(int k=1;k<=hd;++k)
{
int x=q[k]/m+1,y=q[k]%m+1;
for(int i=0;i<4;++i)if(a[x+fx[i]][y+fy[i]])
{
if(f[x][y]+w[i]<f[x+fx[i]][y+fy[i]])
{
f[x+fx[i]][y+fy[i]]=f[x][y]+w[i];
if(!vis[x+fx[i]][y+fy[i]])
{
vis[x+fx[i]][y+fy[i]]=true;
q[++hd]=work(x+fx[i],y+fy[i]);
}
}
}
vis[x][y]=false;
}
}
int main()
{
freopen("robot.in","r",stdin);
freopen("robot.out","w",stdout);
memset(f,10,sizeof(f));
memset(vis,0,sizeof(vis));
n=read(),m=read();int i,j;
for(i=1;i<=n;++i)
for(scanf("%s",s),j=0;j<n;++j)a[i][j+1]=(s[j]=='.');
cin>>l1>>r1>>l2>>r2;
bfs();
cout<<(f[l2][r2]>9999?-1:f[l2][r2])<<endl;
return 0;
}
4.单词方阵
(dcfz.pas/c/cpp)
【问题描述】
给一 n×n 字母方阵,内可能蕴含多个“yizhong”单词。单词在方阵中是沿着同一方向连续摆放的。摆放可沿着 8 个方向的任一方向,同一单词摆放时不再改变方向,单词与单词之间可以交叉,因此有可能共用字母。输出时,将不是单词的字母用*代替,以突出显示单词。
【输入】
第一行输入一个数 n 。( 7≤n≤100)。
第二行开始输入 n×n 的字母矩阵。
【输出】
突出显示单词的 n×n 矩阵。
【输入输出样例1】
8 qyizhong gydthkjy nwidghji orbzsfgz hhgrhwth zzzzzozo iwdfrgng yyyygggg | *yizhong gy****** n*i***** o**z**** h***h*** z****o** i*****n* y******g |
【输入输出样例2】
7 aaaaaaa aaaaaaa aaaaaaa aaaaaaa aaaaaaa aaaaaaa aaaaaaa | ******* ******* ******* ******* ******* ******* ******* |
这题就不算搜索了,但也可以这么说………………………………(我在说什么?)找到y后,枚举每一个方向即可,代码量还行
#include<bits/stdc++.h>
using namespace std;
int n,i,j,l,f[101][101],b;
char a[101][101],s[]="yizhong";
int main()
{
freopen("dcfz.in","r",stdin);
freopen("dcfz.out","w",stdout);
for(scanf("%d\n",&n),i=1;i<=n;i++)
scanf("%s",&a[i]);
for (i=1;i<=n;i++)
for(j=0;j<n;j++)
if(a[i][j]=='y')
{
if(j+6<n)b=1;
else b=0;
if(j+6<n)
for(l=1;l<=6;l++)
if(a[i][j+l]!=s[l]){b=0;break;}
if(b)
for(l=0;l<=6;l++)f[i][j+l]=1;
if(i+6<=n)b=1;
else b=0;
if(i+6<=n)
for(l=1;l<=6;l++)
if(a[i+l][j]!=s[l]){b=0;break;}
if(b)
for(l=0;l<=6;l++)f[i+l][j]=1;
if(j-6>=0)b=1;
else b=0;
if(j-6>=0)
for(l=1;l<=6;l++)
if(a[i][j-l]!=s[l]){b=0;break;}
if(b)
for(l=0;l<=6;l++)f[i][j-l]=1;
if(i-6>0)b=1;
else b=0;
if(i-6>0)
for(l=1;l<=6;l++)
if(a[i-l][j]!=s[l]){b=0;break;}
if(b)
for(l=0;l<=6;l++)
f[i-l][j]=1;
if((i-6>0)&&(j-6>=0))b=1;
else b=0;
if((i-6>0)&&(j-6>=0))
for(l=1;l<=6;l++)
if(a[i-l][j-l]!=s[l]){b=0;break;}
if(b)
for(l=0;l<=6;l++)f[i-l][j-l]=1;
if((i-6>0)&&(j+6<n))b=1;
else b=0;
if((i-6>0)&&(j+6<n))
for(l=1;l<=6;l++)
if(a[i-l][j+l]!=s[l]){b=0;break;}
if(b)
for(l=0;l<=6;l++)f[i-l][j+l]=1;
if((i+6<=n)&&(j-6>=0))b=1;
else b=0;
if((i+6<=n)&&(j-6>=0))
for(l=1;l<=6;l++)
if(a[i+l][j-l]!=s[l]){b=0;break;}
if(b)
for(l=0;l<=6;l++)f[i+l][j-l]=1;
if((i+6<=n)&&(j+6<n))b=1;
else b=0;
if((i+6<=n)&&(j+6<n))
for(l=1;l<=6;l++)
if(a[i+l][j+l]!=s[l]){b=0;break;}
if(b)
for(l=0;l<=6;l++)f[i+l][j+l]=1;
}
for(i=1;i<=n;i++)
{
for(j=0;j<n;j++)
if(f[i][j])printf("%c",a[i][j]);
else printf("*");
printf("\n");
}
fclose(stdout);
fclose(stdin);
return 0;
}
谢谢观赏