BZOJ 1085(IDA*)

 

题面

传送门

分析

首先,直接搜索肯定会TLE
很容易想到用迭代加深的方法,限定搜索深度
但是,这样仍然不够,需要用启发式的方法优化
我们设计一个估价函数f(x)=g(x)+h(x)f(x)=g(x)+h(x)
g(x)g(x)是初始状态到当前状态的实际代价
h(x)h(x)是当前到目标的估计代价
如果f(x)=g(x)+h(x)>df(x)=g(x)+h(x)>d(当前限定深度),则直接返回
h(x)h(x)函数如何设计?
h(x)h(x)不能劣于实际最优值,所以可设为当前状态与目标状态不同方格的数量

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 16
using namespace std;
int n=5;
int walkx[10]= {1,1,-1,-1,2,2,-2,-2};
int walky[10]= {2,-2,2,-2,1,-1,1,-1};
char now[maxn][maxn];
char final[maxn][maxn]= {{},{' ','1','1','1','1','1'},{' ','0','1','1','1','1'},{' ','0','0','*','1','1'},{' ','0','0','0','0','1'},{' ','0','0','0','0','0'}};
int is_same() {
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=n; j++) {
            if(now[i][j]!=final[i][j]) return 0;
        }
    }
    return 1;
}
int h() { //估价函数
    int cnt=0;
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=n; j++) {
            if(now[i][j]!=final[i][j]) cnt++;
        }
    }
    return cnt;
}
int ida(int deep,int limit,int x,int y) {
//  printf("%d %d %d %d\n",deep,dasadfslimit,x,y);
//  for(int i=1; i<=n; i++) {
//      for(int j=1; j<=n; j++) {
//          printf("%c",now[i][j]);
//      }
//      printf("\n");
//  }
//  printf("\n");
    if(deep>limit) return 0;
    if(deep==limit) {
        if(is_same()) {
//          for(int i=1; i<=n; i++) {
//              for(int j=1; j<=n; j++) {
//                  printf("%c",now[i][j]);
//              }
//              printf("\n");
//          }
            return 1;
        } else return 0;
    }
    int flag=0;
    for(int i=0; i<8; i++) {
        int xx=x+walkx[i],yy=y+walky[i];
        if(xx<1||yy<1||xx>n||yy>n) continue;
        swap(now[x][y],now[xx][yy]);
        if(deep+h()<=limit) flag|=ida(deep+1,limit,xx,yy);
        swap(now[x][y],now[xx][yy]);
    }
    return flag;
}
int t;
int main() {
    scanf("%d",&t);
    while(t--) {
        int sx,sy;
        for(int i=1; i<=5; i++) {
            for(int j=1; j<=5; j++) {
                cin>>now[i][j];
                if(now[i][j]=='*') {
                    sx=i;
                    sy=j;
                }
            }
        }
//      for(int i=1; i<=n; i++) {
//          for(int j=1; j<=n; j++) {
//              printf("%c",final[i][j]);
//          }
//          printf("\n");
//      }
        for(int i=0; i<=16; i++) {
            if(i==16) {
                printf("-1\n");
                break;
            }
            if(ida(0,i,sx,sy)) {
                printf("%d\n",i);
                break;
            }
        }
    }
}
posted @ 2018-08-17 08:30  birchtree  阅读(79)  评论(0编辑  收藏