1.跳马
描述:在国际象棋中,马的走法与中车象棋类似,即俗话说的“马走日”,下图所示即国际象棋中马(K)在一步能到达的格子(其中黑色的格子是能到达的位置)。
现有一200*200大小的国际象棋棋盘,棋盘中仅有一个马,给定马的当前位置(S)和目标位置(T),求出马最少需要多少跳才能从当前位置到达目标位置。
输入:本题包含多个测例。输入数据的第一行有一个整数N(1<=N<=1000),表示测例的个数,接下来的每一行有四个以空格分隔的整数,分别表示马当前位置及目标位置的横、纵坐标C(x,y)和G(x,y)。坐标由1开始。
输出:对于每个测例,在单独的一行内输出一个整数,即马从当前位置跳到目标位置最少的跳数。
输入样例
2
1 1 2 1
1 5 5 1
输出样例
3
4
#include<iostream>
#include<queue>
using namespace std;
int cx,cy,gx,gy;
int a[201][201]={0};
int step[201][201];
//马走的方向所对应的行列变化
int b[8]={-2,-2,-1,-1,1,1,2,2};
int c[8]={-1,1,-2,2,-2,2,-1,1};
//结构体内定义队列
struct add
{
queue<int>q1;
queue<int>q2;
}add;
int search(int x,int y);
int main()
{
int n,i,j,k=0;
cin>>n;
int ans[n];
while(k<n)
{
cin>>cx>>cy>>gx>>gy;
//初始化
step[cx][cy]=0;
a[cx][cy]=1;
add.q1.push(cx);
add.q2.push(cy);
ans[k++]=search(cx,cy);
//清空棋盘和队列,防止下一组测试受到影响
for(i=0;i<201;i++)
{
for(j=0;j<201;j++)
{
a[i][j]=0;
step[i][j]=0;
}
}
while(!add.q1.empty())
{
add.q1.pop();
}
while(!add.q2.empty())
{
add.q2.pop();
}
}
for(i=0;i<n;i++)
{
cout<<ans[i]<<endl;
}
return 0;
}
int search(int x,int y)
{
int xt,yt,e,f,i;
while(1)
{
e=add.q1.front();
add.q1.pop();
f=add.q2.front();
add.q2.pop();
for(i=0;i<8;i++)
{
xt=e+b[i];
yt=f+c[i];
if(xt==gx&&yt==gy)
{
return(step[e][f]+1);
}
if(xt<1||xt>200||yt<1||yt>200) continue;//剪枝数组越界的情况
if(a[xt][yt]==0)
{//处理下一组可能的情况
a[xt][yt]=1;
step[xt][yt]=step[e][f]+1;
add.q1.push(xt);
add.q2.push(yt);
}
}
}
}
2.独轮车
描述:独轮车的轮子上有红、黄、蓝、白、绿(依顺时针序)5种颜色,在一个如下图所示的20*20的迷宫内每走一个格子,轮子上的颜色变化一次。独轮车只能向前推或在原地转向。每走一格或原地转向90度均消耗一个单位时间。现给定一个起点(S)和一个终点(T),求独轮车以轮子上的指定颜色到达终点所需的最短时间。
输入:本题包含一个测例。测例中分别用一个大写字母表示方向和轮子的颜色,其对应关系为:E-东、S-南、W-西、N-北;R-红、Y-黄、B-蓝、W-白、G-绿。在测试数据的第一行有以空格分隔的两个整数和两个大写字母,分别表示起点的坐标S(x,y)、轮子的颜色和开始的方向,第二行有以空格分隔的两个整数和一个大写字母,表示终点的坐标T(x,y)和到达终点时轮子的颜色,从第三行开始的20行每行内包含20个字符,表示迷宫的状态。其中'X'表示建筑物,'.'表示路.
输出:在单独的一行内输出一个整数,即满足题目要求的最短时间。
输入样例
3 4 R N
15 17 Y
XXXXXXXXXXXXXXXXXXXX
X.X...XXXXXX......XX
X.X.X.....X..XXXX..X
X.XXXXXXX.XXXXXXXX.X
X.X.XX....X........X
X...XXXXX.X.XX.X.XXX
X.X.XX....X.X..X.X.X
X.X.X..XX...XXXX.XXX
X.X.XX.XX.X....X.X.X
X.X....XX.X.XX.X.X.X
X.X.X.XXXXX.XX.X.XXX
X.X.X.XXXXX....X...X
X.X.......X.XX...X.X
X.XXX.XXX.X.XXXXXXXX
X.....XX.......X...X
XXXXX....X.XXXXXXX.X
X..XXXXXXX.XXX.XXX.X
X.XX...........X...X
X..X.XXXX.XXXX...XXX
XXXXXXXXXXXXXXXXXXXX
输出样例
56
#include<iostream>
#include<queue>
using namespace std;
char map[20][20];
bool canuse[20][20][5][6];
int step[20][20][5][6];
int tx, ty, tcolor;
int ans;
int gorow[4] = {-1, 0, 1, 0};
int gocol[4] = {0, 1, 0, -1};
struct horse{
queue <int> row;
queue <int> col;
queue <int> dire;
queue <int> color;
}horse;
void init();
int search();
int change(char c);
int main(){
init();
ans = search();
cout << ans <<endl;
return 0;
}
void init(){
int i, j, k, l;
int cx, cy;
char cdir;
char ccol;
char tcol;
cin >> cx >> cy >> ccol >> cdir;
cin >> tx >> ty >> tcol;
for(i = 0; i < 20; i++){
for(j = 0; j < 20; j++){
cin >> map[i][j];
if(map[i][j] == 'X'){
for(k = 0; k < 4; k++){
for(l = 0; l < 5; l++){
canuse[i][j][k][l] = false;
}
}
}
else{
for(k = 0; k < 4; k++){
for(l = 0; l < 5; l++){
canuse[i][j][k][l] = true;
}
}
}
}
}
tcolor = change(tcol);
step[cx-1][cy-1][change(cdir)][change(ccol)] = 0;
horse.row.push(cx-1);
horse.col.push(cy-1);
horse.dire.push(change(cdir));
horse.color.push(change(ccol));
canuse[cx-1][cy-1][change(cdir)][change(ccol)] = false;
}
int change(char c){
if(c == 'N') return 0;
if(c == 'E') return 1;
if(c == 'S') return 2;
if(c == 'W') return 3;
if(c == 'R') return 0;
if(c == 'Y') return 1;
if(c == 'B') return 2;
if(c == 'W') return 3;
if(c == 'G') return 4;
}
int search(){
int nx, ny, vx, vy;
int ndire, ncolor, vdire, vcolor;
int i;
while(1){
nx = horse.row.front();
ny = horse.col.front();
ndire = horse.dire.front();
ncolor = horse.color.front();
horse.row.pop();
horse.col.pop();
horse.dire.pop();
horse.color.pop();
for(i = 0; i < 3; i++){ //0表示顺时针转向,1表示逆时针转向,2表示向前走一步
if(i == 0){
vcolor = ncolor;
vdire = (ndire+1)%4;
vx = nx;
vy = ny;
}
else if(i == 1){
vcolor = ncolor;
vdire = (ndire+3)%4;
vx = nx;
vy = ny;
}
else{
vcolor = (ncolor+1)%5;
vdire = ndire;
vx =nx + gorow[ndire];
vy =ny + gocol[ndire];
}
if(vx == tx-1 && vy == ty-1 && vcolor == tcolor){
return(step[nx][ny][ndire][ncolor] + 1);
}
if(vx >= 0 && vx < 20 && vy >= 0 && vy < 20 && canuse[vx][vy][vdire][vcolor]){
horse.row.push(vx);
horse.col.push(vy);
horse.dire.push(vdire);
horse.color.push(vcolor);
canuse[vx][vy][vdire][vcolor] = false;
step[vx][vy][vdire][vcolor] = step[nx][ny][ndire][ncolor] + 1;
}
}
}
}
3.六数码问题
描述:现有一两行三列的表格如下:
A B C
D E F
把1、2、3、4、5、6六个数字分别填入A、B、C、D、E、F格子中,每个格子一个数字且各不相同。每种不同的填法称为一种布局。如下:
1 3 5
2 4 6
布局1
2 5 6
4 3 1
布局2
定义α变换如下:把A格中的数字放入B格,把B格中的数字放入E格,把E格中的数字放入D格,把D格中的数字放入A格。
定义β变换如下:把B格中的数字放入C格,把C格中的数字放入F格,把F格中的数字放入E格,把E格中的数字放入B格。
问:对于给定的布局,可否通过有限次的α变换和β变换变成下面的目标布局:
1 2 3
4 5 6
输入:本题有多个测例,每行一个,以EOF为输入结束标志。每个测例的输入是1到6这六个数字的一个排列,空格隔开,表示初始布局ABCDEF格中依次填入的数字。
输出:每个输出占一行。可以转换的,打印Yes;不可以转换的,打印No。
输入样例
1 3 5 2 4 6
2 5 6 4 3 1
输出样例
No
Yes
提示:第二个示例即布局2的一种转换方法:αααβαα
#include<iostream>
#include<math.h>
#include<queue>
#include<map>
using namespace std;
queue <int> q;
map <int, int> used;
int pow(int x, int y);
int bfs();
int moveto(int v, int i);
int main(){
int num, tmp;
while(cin >> tmp){
num = tmp*pow(10,5);
for(int i = 4; i >= 0; i--){
cin >> tmp;
num += tmp*pow(10,i);
}
while(!q.empty()){
q.pop();
}
used.clear();
q.push(num);
used[num] = 1;
if(bfs()){
cout << "Yes" <<endl;
}
else{
cout << "No" <<endl;
}
}
}
int bfs(){
int u, v;
while(!q.empty()){
u = q.front();
q.pop();
for(int i = 0; i < 2; i++){ //i==0做α变换,i==1做 β变换
v = moveto(u, i);
if(u == 123456){
return 1;
}
if(used[v] == 0){
q.push(v);
used[v] = 1;
}
}
}
return 0;
}
int pow(int x, int y){
int num;
num = x;
if(y == 0){
return 1;
}
for(int i = 0; i < y-1; i++){
num *= x;
}
return num;
}
int moveto(int v, int i){
int a, b, c, d, e, f, tmp;
f = v%10; v = v/10;
e = v%10; v = v/10;
d = v%10; v = v/10;
c = v%10; v = v/10;
b = v%10; v = v/10;
a = v%10;
if(i == 0){
tmp = a;
a = d;
d = e;
e = b;
b = tmp;
}
else{
tmp = b;
b = e;
e = f;
f = c;
c = tmp;
}
for(int i = 0; i < 6; i++){
return(a*pow(10,5)+b*pow(10,4)+c*pow(10,3)+d*pow(10,2)+e*pow(10,1)+f);
}
}
4.找倍数
描述:对于每个输入的数字(如:2),则要求 给出一个由1,0构成的十进制整数,且该整数为输入数字的某个倍数,且是满足该条件的最小数(如2对应的10)。
输入:数字n,n等于0时停止。
输出:n的一个满足条件的最小倍数。
输入样例
2
0
输出样例
10
#include<iostream>
#include<queue>
using namespace std;
long long n;
queue <long long> q;
void search();
int main(){
while(cin >> n && n != 0){
if(n == 1){
cout << '1' << endl;
}
else{
while(!q.empty()){
q.pop();
}
q.push(1);
search();
}
}
return 0;
}
void search(){
long long u, v;
int flag = 0;
while(!q.empty()){
if(flag){
break;
}
u = q.front();
q.pop();
for(int i = 0; i < 2; i++){
v = u*10 + i;
if(v % n == 0){
cout << v << endl;
flag = 1;
break;
}
else{
q.push(v);
}
}
}
}
5.八数码问题
描述:在九宫格里放在1到8共8个数字还有一个是空格,与空格相邻的数字可以移动到空格的位置,问给定的状态最少需要几步能到达目标状态(用0表示空格):
1 2 3
4 5 6
7 8 0
输入:输入一个给定的状态。
输出:输出到达目标状态的最小步数。不能到达时输出-1。
输入样例:
1 2 3
4 0 6
7 5 8
输出样例:
2
#include<iostream>
#include<queue>
#include<map>
using namespace std;
queue <int> q;
map <int, int> step;
map <int, int> used;
void init();
int bfs();
bool canmove(int u, int i);
int move(int u, int i);
int tx[4] = {0, 1, 0, -1};
int ty[4] = {1, 0, -1, 0};
int main(){
init();
cout << bfs() << endl;
return 0;
}
void init(){
int i;
int tmp, num;
cin >> tmp;
num = tmp;
for(i = 0; i < 8; i++){
cin >> tmp;
num = num*10 + tmp;
}
step.clear();
used.clear();
q.push(num);
step[num] = 0;
used[num] = 1;
}
int bfs(){
int i;
int u, v;
u = q.front();
if(u == 123456780){
return 0;
}
while(!q.empty()){
u = q.front();
q.pop();
for(i = 0; i < 4; i++){ //分别向右,下,左,上交换
if(canmove(u, i)){
v = move(u, i);
if(v == 123456780){
return(step[u] + 1);
}
if(used.count(v) == 0){
q.push(v);
step[v] = step[u] + 1;
used[v] = 1;
}
}
}
}
return -1;
}
bool canmove(int u, int i){
int arr[3][3];
int j, k;
int row, col;
int vx, vy;
for(j = 2; j >= 0; j--){
for(k = 2; k >= 0; k--){
arr[j][k] = u%10;
u = u/10;
if(arr[j][k] == 0){
row = j;
col = k;
}
}
}
vx = row + tx[i];
vy = col + ty[i];
if(vx >= 0 && vx < 3 && vy >= 0 && vy < 3){
return true;
}
else{
return false;
}
}
int move(int u, int i){
int arr[3][3];
int j, k;
int row, col;
int vx, vy;
int num;
for(j = 2; j >= 0; j--){
for(k = 2; k >= 0; k--){
arr[j][k] = u%10;
u = u/10;
if(arr[j][k] == 0){
row = j;
col = k;
}
}
}
vx = row + tx[i];
vy = col + ty[i];
arr[row][col] = arr[vx][vy];
arr[vx][vy] = 0;
num = 0;
for(j = 0; j < 3; j++){
for(k = 0; k < 3; k++){
num = num*10 + arr[j][k];
}
}
return num;
}