1. 程式人生 > >10.13—廣搜 //特殊的二階魔方//推箱子//polygon//木乃伊迷宮

10.13—廣搜 //特殊的二階魔方//推箱子//polygon//木乃伊迷宮

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;
	}
}