BZOJ1085/SCOI2005/骑士精神

Posted on By 二价氢

裸搜+最优化剪枝+估价剪枝

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const char s[][6]={
    "11111",
    "01111",
    "00*11",
    "00001",
    "00000"
};
const int
    dx[]={-2,-2,-1,-1, 1, 1, 2, 2},
    dy[]={-1, 1,-2, 2,-2, 2,-1, 1};
char a[6][6];
int ans;
void dfs(int dep,int x,int y,int e,int l)
{
    if (!e)
    {
        ans=dep;
        return;
    }
    for (int i=0;i<8;i++)
    {
        if (i!=7-l)
        {
            int tx=x+dx[i],ty=y+dy[i];
            if (tx>=0&&tx<=4&&ty>=0&&ty<=4)
            {
                int te=e-(a[x][y]!=s[x][y])-(a[tx][ty]!=s[tx][ty]);
                swap(a[x][y],a[tx][ty]);
                te+=(a[x][y]!=s[x][y])+(a[tx][ty]!=s[tx][ty]);
                if (dep+te<ans)
                    dfs(dep+1,tx,ty,te,i);
                swap(a[x][y],a[tx][ty]);
            }
        }
    }
}
void solve()
{
    int x,y,e=0;
    ans=16;
    for (int i=0;i<5;i++)
        for (int j=0;j<5;j++)
        {
            cin>>a[i][j];
            if (a[i][j]=='*')
                x=i,y=j;
            e+=a[i][j]!=s[i][j];
        }
    dfs(0,x,y,e,-1);
    printf("%d\n",((ans<16)?(ans):(-1)));
}
int main()
{
    int t;
    scanf("%d",&t);
    while (t--)
        solve();
    return 0;
}