10.13—廣搜 //特殊的二階魔方//推箱子//polygon//木乃伊迷宮
阿新 • • 發佈:2018-12-16
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;
}
}