1.特殊的二阶魔方
描述:魔方大家应该都玩过。现在有一个特殊的二阶魔方,它只有一面是白色,其余五个面全是黑色。玩这个魔方当然也有特殊的规则,玩家只能通过六种方式去改变它,底层向左转一格(称为DL),底层向右转一格(称为DR),右侧向上转一格(称为RU),右侧向下转一格(称为RD),内侧顺时针转一格(称为C),内侧逆时针转一格(称为CC)。现给一魔方的状态,请在最少的步骤内把魔方还原
输入:按照上下左右前后的顺序给出各面的具体情况,0表示白色,1表示黑色。上下、左右、前后分别是以俯视图、左视图、正视图看到的
输出:输出令一面全为白色的最小步数。
输入样例:
00
00
11
11
11
11
11
11
11
11
11
11
输出样例:
0
#include <iostream>
#include <queue>
using namespace std;
struct node
{
int num[6];
int cube[6][4];
};
queue <node> q1;
int step[16][16][16][16][16][16];
int used[16][16][16][16][16][16];
int bfs();
node setnum(node n1);
node moveto(node n1, int d);
int canmoveto(node n1, node n2); //对n2节点进行判重
int judge(node n1);
int main()
{
node start;
for(int i=0; i<6; i++)
{
for(int j=0; j<4; j++)
{
start.cube[i][j]=cin.get()-'0';
if(j==1)cin.get();
}
cin.get();
}
start=setnum(start);
if(judge(start))
{
cout<<'0'<<endl;
}
else
{
q1.push(start);
step[start.num[0]][start.num[1]][start.num[2]][start.num[3]][start.num[4]][start.num[5]]=0;
used[start.num[0]][start.num[1]][start.num[2]][start.num[3]][start.num[4]][start.num[5]]=1;
cout<<bfs()<<endl;
}
return 0;
}
int bfs()
{
node top,next;
while(!q1.empty())
{
top=q1.front();
q1.pop();
for(int i=0; i<6; i++)
{
next=moveto(top,i);
if(canmoveto(top, next))
{
if(judge(next))
{
return step[next.num[0]][next.num[1]][next.num[2]][next.num[3]][next.num[4]][next.num[5]];
}
else
{
q1.push(next);
}
}
}
}
return -1;
}
node setnum(node n1)
{
for(int i=0; i<6; i++) //六个面
{
n1.num[i]=0; //清空num
for(int j=0; j<4; j++) //每面4块,0==白,1==黑,当作4位二进制编码
{
n1.num[i]*=2; //把4位二进制编码转换成十进制,范围应是0-15
n1.num[i]+=n1.cube[i][j];
}
}
return n1; //返回填充了num数组的n1节点
}
//判断n1节点是否到达目标状态
int judge(node n1)
{
int i;
for(i=0; i<6; i++)
{
if(n1.num[i]==0) //目标状态为一面有四个白块,二进制编码为0000
{
return 1; //6个面里只要有一个面为0
}
}
return 0;
}
//判断n2节点是否重复
int canmoveto(node n1, node n2)
{
if(used[n2.num[0]][n2.num[1]][n2.num[2]][n2.num[3]][n2.num[4]][n2.num[5]]==1)
{
return false; //如果重复就返回false
}
else //如果没重复就更新
{
//更新used数组,记录n2节点用过
used[n2.num[0]][n2.num[1]][n2.num[2]][n2.num[3]][n2.num[4]][n2.num[5]]=1;
//更新step数组,到达n2节点所用步数=1+到达n1节点所用步数
step[n2.num[0]][n2.num[1]][n2.num[2]][n2.num[3]][n2.num[4]][n2.num[5]]=
1+step[n1.num[0]][n1.num[1]][n1.num[2]][n1.num[3]][n1.num[4]][n1.num[5]];
//返回true表示不重复
return true;
}
}
node moveto(node n1, int dire)
{
node n2;
for(int i=0; i<6; i++)
{
for(int j=0; j<4; j++)
{
n2.cube[i][j]=n1.cube[i][j];
}
}
switch(dire)
{
case 0: //右侧向上转一格
{
n2.cube[0][1]=n1.cube[4][1]; //上面的1、3块=前面的1、3块
n2.cube[0][3]=n1.cube[4][3];
n2.cube[4][1]=n1.cube[1][3]; //前面的1、3块=下面的3、1块
n2.cube[4][3]=n1.cube[1][1];
n2.cube[1][1]=n1.cube[5][1]; //下面的1、3块=后面的1、3块
n2.cube[1][3]=n1.cube[5][3];
n2.cube[5][1]=n1.cube[0][3]; //后面的1、3块=上面的3、1块
n2.cube[5][3]=n1.cube[0][1];
n2.cube[3][0]=n1.cube[3][1]; //右面的4个块逆时针转
n2.cube[3][1]=n1.cube[3][3];
n2.cube[3][3]=n1.cube[3][2];
n2.cube[3][2]=n1.cube[3][0];
break;
}
case 1: //右侧向下转一格
{
n2.cube[0][1]=n1.cube[5][3]; //上面的1、3块=后面的3、1块
n2.cube[0][3]=n1.cube[5][1];
n2.cube[5][1]=n1.cube[1][1]; //后面的1、3块=下面的1、3块
n2.cube[5][3]=n1.cube[1][3];
n2.cube[1][1]=n1.cube[4][3]; //下面的1、3块=前面的3、1块
n2.cube[1][3]=n1.cube[4][1];
n2.cube[4][1]=n1.cube[0][1]; //前面的1、3块=上面的1、3块
n2.cube[4][3]=n1.cube[0][3];
n2.cube[3][0]=n1.cube[3][2]; //右面的4个块顺时针转
n2.cube[3][2]=n1.cube[3][3];
n2.cube[3][3]=n1.cube[3][1];
n2.cube[3][1]=n1.cube[3][0];
break;
}
case 2: //底层向左转一格
{
n2.cube[2][2]=n1.cube[4][2]; //左面的2、3块=前面的2、3块
n2.cube[2][3]=n1.cube[4][3];
n2.cube[4][2]=n1.cube[3][3]; //前面的2、3块=右面的3、2块
n2.cube[4][3]=n1.cube[3][2];
n2.cube[3][2]=n1.cube[5][2]; //右面的3、2块=后面的2、3块
n2.cube[3][3]=n1.cube[5][3];
n2.cube[5][2]=n1.cube[2][3]; //后面的2、3块=左面的3、2块
n2.cube[5][3]=n1.cube[2][2];
n2.cube[1][1]=n1.cube[1][0]; //下面的4个块顺时针转
n2.cube[1][0]=n1.cube[1][2];
n2.cube[1][2]=n1.cube[1][3];
n2.cube[1][3]=n1.cube[1][1];
break;
}
case 3: //底层向右转一格
{
n2.cube[3][2]=n1.cube[4][3]; //右面的2、3块=前面的3、2块
n2.cube[3][3]=n1.cube[4][2];
n2.cube[4][2]=n1.cube[2][2]; //前面的2、3块=左面的2、3块
n2.cube[4][3]=n1.cube[2][3];
n2.cube[2][2]=n1.cube[5][3]; //左面的2、3块=后面的3、2块
n2.cube[2][3]=n1.cube[5][2];
n2.cube[5][2]=n1.cube[3][2]; //后面的3、2块=右面的2、3块
n2.cube[5][3]=n1.cube[3][3];
n2.cube[1][2]=n1.cube[1][0]; //下面的4个块逆时针转
n2.cube[1][3]=n1.cube[1][2];
n2.cube[1][1]=n1.cube[1][3];
n2.cube[1][0]=n1.cube[1][1];
break;
}
case 4: //内侧顺时针转一格
{
n2.cube[0][2]=n1.cube[2][3]; //上面的2、3块=左面的3、1块
n2.cube[0][3]=n1.cube[2][1];
n2.cube[2][1]=n1.cube[1][2]; //左面的1、3块=下面的2、3块
n2.cube[2][3]=n1.cube[1][3];
n2.cube[1][2]=n1.cube[3][3]; //下面的2、3块=右面的3、1块
n2.cube[1][3]=n1.cube[3][1];
n2.cube[3][1]=n1.cube[0][2]; //右面的1、3块=上面的2、3块
n2.cube[3][3]=n1.cube[0][3];
n2.cube[4][0]=n1.cube[4][2]; //内侧的4个块顺时针转
n2.cube[4][2]=n1.cube[4][3];
n2.cube[4][3]=n1.cube[4][1];
n2.cube[4][1]=n1.cube[4][0];
break;
}
case 5: //内侧逆时针转一格
{
n2.cube[0][2]=n1.cube[3][1]; //上面的2、3=右面的1、3
n2.cube[0][3]=n1.cube[3][3];
n2.cube[3][1]=n1.cube[1][3]; //右面的1、3=下面的3、2
n2.cube[3][3]=n1.cube[1][2];
n2.cube[1][2]=n1.cube[2][1]; //下面的2、3=左面的1、3
n2.cube[1][3]=n1.cube[2][3];
n2.cube[2][1]=n1.cube[0][3]; //左面的1、3=上面的3、2
n2.cube[2][3]=n1.cube[0][2];
n2.cube[4][0]=n1.cube[4][1]; //内侧的4个逆时针转
n2.cube[4][1]=n1.cube[4][3];
n2.cube[4][3]=n1.cube[4][2];
n2.cube[4][2]=n1.cube[4][0];
break;
}
}
return(setnum(n2));
}
2.推箱子
描述:绝大多数人都玩过推箱子的游戏,控制一个人将箱子推动到目标位置即获得胜利。现请你编写一个程序,判断将箱子推到目标位置至少需要多少步。
输入:推箱子的平面区域为固定大小(10*10),使用10行10列输入推箱子的初始局面。其中,0代表空格,1代表墙,2代表箱子,3代表目标位置,4代表人。
注:游戏中只有一个箱子,一个目标位置,一个人。
输出:
输出将箱子推到目标位置的最小步数;若箱子不可能被推到目标位置,输出-1。
输入样例:
0000000000
0000000300
0100000000
0100000000
0101111100
0000010000
0000010000
0020010040
0000010000
0000010000
输出样例:
34
#include<iostream>
#include<queue>
using namespace std;
char map[10][10];
int used[10][10][10][10] = {0};
int step[10][10][10][10];
int rx, ry, bx, by, tx, ty;
struct game{
int rrow;
int rcol;
int brow;
int bcol;
};
queue <game> q;
void readdata();
void init();
int bfs();
game rgo(game u, int dir);
int main(){
readdata();
init();
cout << bfs() << endl;
}
void readdata(){
int i, j;
for(i = 0; i < 10; i++){
for(j = 0; j < 10; j++){
cin >> map[i][j];
if(map[i][j] == '4'){
rx = i; ry = j;
}
if(map[i][j] == '3'){
tx = i; ty = j;
}
if(map[i][j] == '2'){
bx = i; by = j;
}
}
}
}
void init(){
game u;
u.rrow = rx;
u.rcol = ry;
u.brow = bx;
u.bcol = by;
q.push(u);
used[rx][ry][bx][by] = 1;
step[rx][ry][bx][by] = 0;
}
int bfs(){
game u, v;
while(!q.empty()){
u = q.front();
q.pop();
if(u.brow == tx && u.bcol == ty){
return(step[u.rrow][u.rcol][u.brow][u.bcol]);
}
for(int i = 0; i < 4; i++){
v = rgo(u, i);
if(v.rrow < 0 || v.rrow >=10 || v.rcol < 0 || v.rcol >= 10 || map[v.rrow][v.rcol] == '1'){
continue;
}
else{
if(!(v.rrow == v.brow && v.rcol == v.bcol) && !used[v.rrow][v.rcol][v.brow][v.bcol]){
q.push(v);
used[v.rrow][v.rcol][v.brow][v.bcol] = 1;
step[v.rrow][v.rcol][v.brow][v.bcol] = step[u.rrow][u.rcol][u.brow][u.bcol] + 1;
}
else if(v.rrow == v.brow && v.rcol == v.bcol){
if(i == 0 && !used[v.rrow][v.rcol][v.brow][v.bcol+1] && v.bcol<9 && map[v.brow][v.bcol+1] != '1'){
v.bcol = v.bcol + 1;
q.push(v);
used[v.rrow][v.rcol][v.brow][v.bcol] = 1;
step[v.rrow][v.rcol][v.brow][v.bcol] = step[u.rrow][u.rcol][u.brow][u.bcol] + 1;
}
else if(i == 1 && !used[v.rrow][v.rcol][v.brow+1][v.bcol] && v.brow<9 && map[v.brow+1][v.bcol] != '1'){
v.brow = v.brow + 1;
q.push(v);
used[v.rrow][v.rcol][v.brow][v.bcol] = 1;
step[v.rrow][v.rcol][v.brow][v.bcol] = step[u.rrow][u.rcol][u.brow][u.bcol] + 1;
}
else if(i == 2 && !used[v.rrow][v.rcol][v.brow][v.bcol-1] && v.bcol>0 && map[v.brow][v.bcol-1] != '1'){
v.bcol = v.bcol - 1;
q.push(v);
used[v.rrow][v.rcol][v.brow][v.bcol] = 1;
step[v.rrow][v.rcol][v.brow][v.bcol] = step[u.rrow][u.rcol][u.brow][u.bcol] + 1;
}
else if(i == 3 && !used[v.rrow][v.rcol][v.brow-1][v.bcol] && v.brow>0 && map[v.brow-1][v.bcol] != '1'){
v.brow = v.brow - 1 ;
q.push(v);
used[v.rrow][v.rcol][v.brow][v.bcol] = 1;
step[v.rrow][v.rcol][v.brow][v.bcol] = step[u.rrow][u.rcol][u.brow][u.bcol] + 1;
}
}
}
}
}
return -1;
}
game rgo(game u, int dir){
int row[4] = {0, 1, 0, -1};
int col[4] = {1, 0, -1, 0};
u.rrow += row[dir];
u.rcol += col[dir];
return u;
}
3.polygon
描述:在一个周长为10000的圆上等距分布着n个点,即这n个点是一个正n边形的顶点。现在要另加m个点到圆上,新加的m个点可以任意选择位置(可以与原有的点重合)。然后将这n+m个点中的一些点延圆周移动,最终使n+m个点均匀分布,即在一个正n+m边形的顶点上。输出最小总移动距离。
输入:输入两个整数 n, m。 (2≤n≤1000, 1≤m≤1000).
输出:输出最小总移动距离,保留4位小数。
输入样例:
sample input #1 2 1
sample input #2 2 3
sample input #3 3 1
sample input #4 10 10
输出样例:
sample output #1 1666.6667
sample output #2 1000.0
sample output #3 1666.6667
sample output #4 0.0
图对应前3个样例
#include<iostream>
#include<stdio.h>
#include<math.h>
using namespace std;
int main(){
int n, m;
double arr1[2000];
double arr2[2000];
int i, j;
double ans, minn;
while(~scanf("%d%d",&n, &m)){
for(i = 0; i < n; i++){
arr1[i] = i*(10000.0/n);
}
for(i = 0; i < (m+n); i++){
arr2[i] = i*(10000.0/(m+n));
}
ans = 0;
for(i = 0; i < n; i++){
minn = 10000;
for(j = 0; j < (m+n); j++){
minn = min(minn, fabs(arr1[i]-arr2[j]));
}
ans += minn;
}
printf("%.4lf\n", ans);
}
}
4.木乃伊迷宫
描述:木乃伊地下宫殿是一个6行6列的迷宫。作为敢到木乃伊地下宫殿里去探险的你,有没有跟木乃伊抓迷藏的心理准备呵!游戏在木乃伊所在的迷宫里展开,任务就是尽快赶到出口。你一次只能走一步,而木乃伊可以走两步,但木乃伊是很笨的,他总是先尽量跟你达到同一列,如果已经是同一列了,他才会像你走来,有墙的地方人和木乃伊都不能过,你可以利用障碍物牵制住木乃伊。
输入:先输入墙的数量n,然后在后续的n行里每行有3个数表示一堵墙,3个数分别为格子的行、列和墙的位置(0表示这个格子的下方是墙,1表示这个格子的右方是墙),再下来的3行每行2个数,分别表示木乃伊、人还有出口的位置。
输出: 如果能安全逃生则输出Yes,否则输出No,答案占一行。
输入样例:
5
0 0 0
1 1 1
1 4 1
3 4 1
4 3 0
3 3
3 1
5 5
输出样例:
No
#include<iostream>
#include<queue>
using namespace std;
int map[6][6] = {0};
int used[6][6][6][6] = {0};
int mx, my, rx, ry, dx, dy;
struct game{
int rrow;
int rcol;
int mrow;
int mcol;
};
int row[4] = {0, 1, 0 ,-1};
int col[4] = {1, 0, -1, 0};
int flag = 0, flag1;
queue <game> q;
void init();
void dfs();
bool rcanmove(game u, int dir);
game rmove(game u, int dir);
game mmove(game u);
bool getdoor(game u);
bool canto(game u);
bool can(game u);
int main(){
int n;
int i;
int a, b, c;
cin >> n;
for(i = 0; i < n; i++){
cin >> a >> b >> c;
if(c == 1){
map[a][b] = 1;
}
else{
map[a][b] = 2;
}
}
cin >> mx >> my >> rx >>ry >> dx >> dy;
init();
dfs();
if(rx == dx && ry == dy){
flag = 1;
}
if(!flag){
cout << "No" << endl;
}
else{
cout << "Yes" << endl;
}
}
void init(){
game first;
first.rrow = rx;
first.rcol = ry;
first.mrow = mx;
first.mcol = my;
q.push(first);
used[rx][ry][mx][my] = 1;
}
void dfs(){
game u, v;
int i;
while(!q.empty()){
u = q.front();
q.pop();
for(i = 0; i < 4; i++){
if(rcanmove(u, i)){
v = rmove(u, i);
if(getdoor(v)){
flag = 1;
return;
}
if(can(v)){
flag1 = 0;
v = mmove(v);
if(used[v.rrow][v.rcol][v.mrow][v.mcol] == 0 && !flag1){
used[v.rrow][v.rcol][v.mrow][v.mcol] = 1;
q.push(v);
}
}
}
}
}
}
bool rcanmove(game u, int dir){
int nrx, nry;
nrx = u.rrow;
nry = u.rcol;
if(dir == 0){
if(map[nrx][nry] == 1){
return false;
}
}
if(dir == 1){
if(map[nrx][nry] == 2){
return false;
}
}
if(dir == 2){
if(map[nrx][nry-1] == 1){
return false;
}
}
if(dir == 3){
if(map[nrx-1][nry] == 2){
return false;
}
}
return true;
}
game rmove(game u, int dir){
game v;
v.rrow = u.rrow + row[dir];
v.rcol = u.rcol + col[dir];
v.mrow = u.mrow;
v.mcol = u.mcol;
return v;
}
game mmove(game u){
int n = 2;
while(n--){
if((u.rcol > u.mcol) && (map[u.mrow][u.mcol] != 1)){
u.mcol++;
}
else{
if((u.rcol < u.mcol) && (map[u.mrow][u.mcol-1] != 1)){
u.mcol--;
}
else if(u.rcol == u.mcol){
if((u.rrow > u.mrow) && (map[u.mrow][u.mcol] != 2)){
u.mrow++;
}
else if((u.rrow < u.mrow) && (map[u.mrow-1][u.mcol] != 2)){
u.mrow--;
}
else if(u.rrow == u.mrow && u.rcol == u.mcol){
flag1 = 1;
break;
}
}
}
}
return u;
}
bool canto(game u){
if(u.rrow == u.mrow && u.mcol == u.rcol){
return false;
}
else{
return true;
}
}
bool getdoor(game u){
if(u.rrow == dx && u.rcol == dy){
return true;
}
else{
return false;
}
}
bool can(game u){
if(u.rrow >= 0 && u.rcol >= 0 && u.rrow < 6 && u.rcol < 6){
return true;
}
else{
return false;
}
}