• 广搜——最优方案


    Wikioi 1225 八数码难题

    题目描述 Description

    Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.
    问题描述

    在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。

    输入描述 Input Description

    输入初试状态,一行九个数字,空格用0表示

    输出描述 Output Description

    只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)

    样例输入 Sample Input

    283104765

    样例输出 Sample Output

    4

    数据范围及提示 Data Size & Hint

    详见试题

    思路:

    (康托展开+双向广搜) or ida*

    代码:

    ①双向广搜:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<string>
      4 #include<cstring>
      5 #include<cmath>
      6 #include<queue>
      7 #include<map>
      8 #include<algorithm>
      9 #define mx 4000000
     10 using namespace std;
     11 
     12 struct chess{
     13     int node[9];
     14     int step;
     15     int pos;
     16     bool cla;
     17 };
     18 int chart = 0,step[2][10000];
     19 map<int,int> trans[2];
     20 chess start,end;
     21 bool jud[2][mx];
     22 int m_jud[9][4] = {1,3,-1,-1,
     23                    0,4,2,-1,
     24                    1,5,-1,-1,
     25                    0,4,6,-1,
     26                    1,3,5,7,
     27                    2,4,8,-1,
     28                    3,7,-1,-1,
     29                    4,6,8,-1,
     30                    5,7,-1,-1};
     31 
     32 int getval(chess x){
     33     int res = 1,val = 0;
     34     for(int i = 1;i <= 9;i++){
     35         val += res * x.node[i-1];
     36         res *= (i+1);
     37     }
     38     return val;
     39 }
     40 void putout(chess pt){
     41     cout<<"the class:"<<pt.cla<<endl;
     42     for(int i = 1;i <= 3;i++){
     43         for(int j = 1;j <= 3;j++){
     44             cout<<pt.node[(i-1) * 3 + j - 1] <<" ";
     45         }
     46         cout<<endl;
     47     }
     48     cout<<"steps: "<<pt.step<<" , pos: "<<pt.pos<<endl;
     49 }
     50 void init(){
     51     int co,md = 1;
     52     cin>>co;
     53     for(int i = 8;i >= 0;i--){
     54         start.node[i] = (co / md)% 10;
     55         md *= 10;
     56         if(start.node[i] == 0) start.pos = i;
     57         
     58     }
     59     start.cla = 0;
     60     end.node[0] = 1;
     61     end.node[1] = 2;
     62     end.node[2] = 3;
     63     end.node[3] = 8;
     64     end.node[4] = 0;
     65     end.node[5] = 4;
     66     end.node[6] = 7;
     67     end.node[7] = 6;
     68     end.node[8] = 5;
     69     end.step = start.step = 0;
     70     end.pos = 4;
     71     end.cla = 1;
     72 }
     73 void bfs(){
     74     queue<chess> now,then;
     75     now.push(start);
     76     now.push(end);
     77     chess test,h;
     78     int p,code;
     79     while(!now.empty()){
     80         h = now.front();
     81         p = h.pos;
     82         code = getval(h);
     83         trans[h.cla][code] = chart;
     84         step[h.cla][chart] = h.step;
     85         chart++;
     86         jud[h.cla][code] = 1;
     87         for(int i = 0,j = m_jud[p][i];j != -1 && i <= 3;i++,j = m_jud[p][i]){
     88             test = h;
     89             test.step++;
     90             swap(test.node[p],test.node[j]);
     91             code = getval(test);
     92             //if(jud[test.cla][code]) continue;
     93             test.pos = j;
     94             trans[test.cla][code] = chart;
     95             step[test.cla][chart] = test.step;
     96             chart++;
     97             if(jud[!test.cla][code]){
     98                 cout<<step[0][trans[0][code]] + step[1][trans[1][code]]<<endl;
     99                 return;
    100             }
    101             if(!jud[test.cla][code]){
    102                 now.push(test);
    103                 jud[test.cla][code] = 1;
    104             }
    105             
    106         }
    107         now.pop();
    108     }
    109 }
    110 int main(){
    111 
    112     init();    
    113     bfs();
    114     return 0;
    115 }
    View Code

    ②IDA*:

      1 #include <iostream>
      2 #include <cmath>
      3 #include <cstdlib>
      4 #include <cstdio>
      5 #include <cstring>
      6 using namespace std;
      7 const unsigned int M = 1001;
      8 int dir[4][2] = {
      9     1, 0, // Down
     10     -1, 0, // Up
     11     0,-1, // Left
     12     0, 1 // Right
     13 };
     14 typedef struct STATUS{
     15     int arr[3][3];
     16     int r,c;
     17 }STATUS;
     18 char dirCode[] = {"dulr"};
     19 char rDirCode[] = {"udrl"};
     20 char path[M]; // 最优解
     21 STATUS begin, end = { 1,2,3,4,5,6,7,8,0,2,2 }; // 起始和终止状态
     22 int maxDepth = 0; // 深度边界
     23 int diff(const STATUS &cur) // 启发函数
     24 {
     25     int i,j,k,m,ans=0;
     26     for(i=0;i<=2;i++)
     27         for(j=0;j<=2;j++)
     28         {
     29             if(cur.arr[i][j] != 0)
     30             {
     31                 for(k=0;k<=2;k++)
     32                     for(m=0;m<=2;m++)
     33                     {
     34                         if(cur.arr[i][j] == end.arr[k][m])
     35                         {
     36                             ans+=abs(i-k)+abs(j-m);
     37                             break;
     38                         }
     39                     }
     40             }
     41         }
     42     return ans;
     43 }
     44 bool dfs(STATUS &cur, int depth, int h, char preDir)
     45 {
     46     if(memcmp(&cur, &end, sizeof(STATUS)) == 0 )
     47     { // OK找到解了:)
     48         path[depth] = '/0';
     49         return true;
     50     }
     51     if( depth + h > maxDepth ) return false; // 剪枝
     52     STATUS nxt; // 下一状态
     53     for(int i=0; i<4; i++)
     54     {
     55         if(dirCode[i]==preDir) continue; // 回到上次状态,剪枝
     56         nxt = cur;
     57         nxt.r = cur.r + dir[i][0];
     58         nxt.c = cur.c + dir[i][1];
     59         if( !( nxt.r >= 0 && nxt.r < 3 && nxt.c >= 0 && nxt.c < 3 ) )
     60             continue;
     61         int nxth = h;
     62         int preLen,Len,desNum=cur.arr[nxt.r][nxt.c],desR=(desNum-1)/3,desC=(desNum-1)%3;
     63         preLen=abs(nxt.r-desR)+abs(nxt.c-desC);
     64         Len=abs(cur.r-desR)+abs(cur.c-desC);
     65         nxth = h - preLen + Len;
     66         swap(nxt.arr[cur.r][cur.c], nxt.arr[nxt.r][nxt.c]);
     67         path[depth] = dirCode[i];
     68         if(dfs(nxt, depth + 1, nxth, rDirCode[i]))
     69             return true;
     70     }
     71     return false;
     72 }
     73 int IDAstar()
     74 {
     75     int nh = diff(begin);
     76     maxDepth = nh;
     77     while (!dfs(begin, 0, nh, '/0'))
     78         maxDepth++;
     79     return maxDepth;
     80 }
     81 void Input()
     82 {
     83     char ch;
     84     int i, j;
     85     for(i=0; i < 3; i++){
     86         for(j=0; j < 3; j++){
     87             do{
     88                 scanf("%c", &ch);
     89             }
     90             while( !( ( ch >= '1' && ch <= '8' ) || ( ch == 'x' ) ) ) 
     91                 ;
     92             if( ch == 'x' ) {
     93                 begin.arr[i][j] = 0;
     94                 begin.r = i;
     95                 begin.c = j;
     96             }
     97             else
     98                 begin.arr[i][j] = ch - '0';
     99         }
    100     }
    101 }
    102 bool IsSolvable(const STATUS &cur)
    103 {
    104     int i, j, k=0, s = 0;
    105     int a[8];
    106     for(i=0; i < 3; i++){
    107         for(j=0; j < 3; j++){
    108             if(cur.arr[i][j]==0) continue;
    109             a[k++] = cur.arr[i][j];
    110         }
    111     }
    112     for(i=0; i < 8; i++){
    113         for(j=i+1; j < 8; j++){
    114             if(a[j] < a[i])
    115                 s++;
    116         }
    117     }
    118     return (s%2 == 0);
    119 }
    120 int main()
    121 {
    122     Input();
    123     if(IsSolvable(begin)){
    124         IDAstar();
    125         printf("%s/n", path);
    126     }
    127     else
    128         printf("unsolvable/n");
    129     return 0;
    130 }
    View Code

    Wikioi 2449 骑士精神

    题目描述 Description

         在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位。在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空位上。

            给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘:

                             

    为了体现出骑士精神,他们必须以最少的步数完成任务。

    输入描述 Input Description

    第一行有一个正整数T(T<=10),表示一共有N组数据。接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士,*表示空位。两组数据之间没有空行。

    输出描述 Output Description

    对于每组数据都输出一行。如果能在15步以内(包括15步)到达目标状态,则输出步数,否则输出-1。

    样例输入 Sample Input
    2
    10110
    01*11
    10111
    01001
    00000
    01011
    110*1
    01110
    01010
    00100
    样例输出 Sample Output

    7

    -1

    数据范围及提示 Data Size & Hint

    见题面

    思路:

    IDA*

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<string>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<algorithm>
     7 #define mx 5
     8 using namespace std;
     9 struct Board{
    10     int board[mx][mx];
    11     int bx,by;
    12     
    13 };
    14 int ans[mx][mx] = {{1,1,1,1,1},
    15                    {2,1,1,1,1},
    16                    {2,2,0,1,1},
    17                    {2,2,2,2,1},
    18                    {2,2,2,2,2}};
    19 int dx[8] = {1,2,2,1,-1,-2,-2,-1};
    20 int dy[8] = {2,1,-1,-2,-2,-1,1,2};
    21 int d,id,bx,by;
    22 Board start;
    23 void input(){
    24     char tmp;
    25     for(int i = 0;i < 5;i++){
    26         for(int j = 0;j < 5;j++){
    27             cin>>tmp;
    28             if(tmp == '*'){
    29                 start.board[i][j] = 0;
    30                 by = i;
    31                 bx = j;
    32             }
    33             if(tmp == '1') start.board[i][j] = 1;
    34             if(tmp == '0') start.board[i][j] = 2;
    35         }
    36     }
    37 }
    38 int h(Board a){
    39     int ret = 0;
    40     for(int i = 0;i < 5;i++){
    41         for(int j = 0;j < 5;j++){
    42             ret += (ans[i][j] != a.board[i][j]);
    43         }
    44     }
    45     return ret;
    46 }
    47 bool idastar(int step,int maxdeep){
    48     if(step > maxdeep) return false;
    49     int g = h(start),bx,by;
    50     if(!g) return true;
    51     if(g + step - 1> maxdeep) return false;
    52     for(int i = 0;i < 5;i++){
    53         for(int j = 0;j < 5;j++){
    54             if(start.board[i][j] == 0){
    55                 bx = j;
    56                 by = i;
    57             }
    58         }
    59     }
    60     for(int i = 0;i < 8;i++){
    61         if(bx + dx[i] < 0 || bx + dx[i] >= mx || by + dy[i] < 0 || by + dy[i] >= mx) continue;
    62         swap(start.board[by + dy[i]][bx + dx[i]],start.board[by][bx]);
    63         if(idastar(step+1,maxdeep))return true;
    64         swap(start.board[by + dy[i]][bx + dx[i]],start.board[by][bx]);
    65     }
    66     return false;
    67 }
    68 int main(){
    69     int T;
    70     cin>>T;
    71     while(T--){
    72     input();
    73     for(id = 0;id <= 15;id++){
    74         if(idastar(0,id)){
    75             cout<<id<<endl;
    76             break;
    77         }
    78     }
    79     if(id > 15) cout<<-1<<endl;
    80 }
    81     return 0;
    82 }
    View Code

    Wikioi 1226 倒水问题

    题目描述 Description

    有两个无刻度标志的水壶,分别可装 x 升和 y 升 ( x,y 为整数且均不大于 100 )的水。设另有一水 缸,可用来向水壶灌水或接从水壶中倒出的水, 两水壶间,水也可以相互倾倒。已知 x 升壶为空 壶, y 升壶为空壶。问如何通过倒水或灌水操作, 用最少步数能在x或y升的壶中量出 z ( z ≤ 100 )升的水 来。

    输入描述 Input Description

    一行,三个数据,分别表示 x,y 和 z;

    输出描述 Output Description

    一行,输出最小步数 ,如果无法达到目标,则输出"impossible"

    样例输入 Sample Input

    3 22 1

    样例输出 Sample Output

    14

    思路:

    普通广搜

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<string>
     4 #include<cstring>
     5 #include<algorithm>
     6 #define maxn 100000
     7 using namespace std;
     8 struct sta{
     9     int x;
    10     int y; 
    11     int step;
    12     int frm;
    13 };
    14 int mx,my,z,j[101][101],solved = 0;
    15 sta temp;
    16 void input(){
    17     cin>>mx>>my>>z;
    18     temp.x = temp.y = temp.step = 0;
    19     temp.frm = -1;
    20 }
    21 sta expand(sta a,int sign){
    22     if(sign == 0) a.x = 0;
    23     if(sign == 1) a.y = 0;
    24     if(sign == 2) a.x = mx;
    25     if(sign == 3) a.y = my;
    26     if(sign == 4){
    27         int d;
    28         if(mx - a.x < a.y) d = mx - a.x;
    29         else d = a.y;
    30         a.y -= d;
    31         a.x += d;
    32     }
    33     if(sign == 5){
    34         int d;
    35         if(my - a.y < a.x) d = my - a.y;
    36         else d = a.x;
    37         a.y += d;
    38         a.x -= d;
    39     }
    40     a.frm = sign;
    41     a.step++;
    42     if(j[a.x][a.y]) a.step = -1;
    43     j[a.x][a.y] = 1;
    44     return a;
    45 }
    46 void bfs(){
    47     sta q[maxn];
    48     int h = 0,t = 1;
    49     q[h] = temp;
    50     while(h != t){
    51         if(q[h%maxn].x == z || q[h%maxn].y == z) {
    52             cout<<q[h%maxn].step<<endl;
    53             solved = 1;
    54             break;
    55         }
    56         for(int i = 0;i <= 5;i++){
    57            if(i == 0 && (q[h%maxn].x == 0 ||q[h%maxn].frm == 2)) continue;
    58            if(i == 1 && (q[h%maxn].y == 0 ||q[h%maxn].frm == 3)) continue;
    59            if(i == 2 && (q[h%maxn].x == mx ||q[h%maxn].frm == 0)) continue;
    60            if(i == 3 && (q[h%maxn].y == my ||q[h%maxn].frm == 1)) continue;
    61            if(i == 4 && (q[h%maxn].y <= 0 || q[h%maxn].x >= mx || q[h%maxn].frm == 5)) continue;
    62            if(i == 5 && (q[h%maxn].x <= 0 || q[h%maxn].y >= my || q[h%maxn].frm == 4)) continue;
    63            temp = expand(q[h%maxn],i);
    64            
    65            if(temp.step != -1) {
    66                t++;
    67                    q[t%maxn] = temp;
    68                       
    69            }
    70         }
    71         h++;
    72     }
    73 }
    74 int main(){
    75     input();
    76     if(z > mx || z > my || !mx || !my || (mx == my && mx != z)){
    77         cout<<"impossible"<<endl;
    78         return 0;
    79     }
    80     bfs();
    81     if(!solved)    cout<<"impossible"<<endl;
    82     return 0;
    83 }
    View Code
  • 相关阅读:
    03-django模型(1)
    Django02 Django基础知识
    jquery
    Django01 web http 基础
    Python之协程
    Python之线程
    进程 操作
    CSS
    UVALive-3268 Jamie's Contact Groups (最大流,网络流建模)
    UVA-10806 Dijkstra, Dijkstra. (最小费用流,网络流建模)
  • 原文地址:https://www.cnblogs.com/hyfer/p/4842112.html
Copyright © 2020-2023  润新知