华师一附中OI组
标题:
P2324 [SCOI2005]骑士精神
[打印本页]
作者:
admin
时间:
2018-5-21 12:17
标题:
P2324 [SCOI2005]骑士精神
https://www.luogu.org/problemnew/show/P2324
输入输出格式
输入格式:
第一行有一个正整数T(T<=10),表示一共有N组数据。接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士,*表示空位。两组数据之间没有空行。
输出格式:
对于每组数据都输出一行。如果能在15步以内(包括15步)到达目标状态,则输出步数,否则输出-1。
输入输出样例
输入样例#1:
2
10110
01*11
10111
01001
00000
01011
110*1
01110
01010
00100
输出样例#1:
7
-1
说明
作者:
lyc
时间:
2018-5-27 10:47
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
const int oo = 0x3f3f3f3f;
using namespace std;
int chest[10][10];
int ans;
int pd[6][6] = {+0, +0, +0, +0, +0, +0,
+0, +1, +1, +1, +1, +1,
+0, +0, +1, +1, +1, +1,
+0, +0, +0, -1, +1, +1,
+0, +0, +0, +0, +0, +1,
+0, +0, +0, +0, +0, +0
};
int fx[8]={+1,+1,-1,-1,+2,+2,-2,-2};
int fy[8]={+2,-2,+2,-2,+1,-1,+1,-1};
bool flag = 0;
inline int rem(){
int ans=0;
for(int i=1;i<=5;i++){
for(int j=1;j<=5;j++){
if(pd[i][j] != chest[i][j]) ans++;
}
}
return ans;
}
void dfs(int now, int last, int x, int y)
{
int remain = rem();
if(remain + now > 16 || now > ans) return;
if(remain == 0)
{
ans = now;
flag = 1;
return;
}
for(int i=0; i<=7; i++)
{
int nx = x + fx[i];
int ny = y + fy[i];
if(nx<1 || nx>5 || ny<1 || ny>5 || i == 7-last) continue;
swap(chest[nx][ny], chest[x][y]);
dfs(now+1, i, nx, ny);
swap(chest[nx][ny], chest[x][y]);
}
}
int t;
int main()
{
cin>>t;
while(t--)
{
memset(chest, 0, sizeof(chest));
flag = 0;
ans = oo;
int sx,sy;
char k;
for(int i=1; i<=5; i++)
for(int j=1; j<=5; j++)
{
cin>>k;
if(k=='*')
{
chest[i][j]=-1;
sx=i;
sy=j;
}
else chest[i][j]= k - '0';
}
dfs(0, 0, sx, sy);
if(!flag)
{
cout<<-1<<endl;
continue;
}
else cout<<ans<<endl;
}
return 0;
}
复制代码
luogu最后一个点wa不知道为什么
作者:
张笑宇
时间:
2018-6-1 22:54
#include<iostream>
using namespace std;
int m[6][6]= {0,0,0,0,0,0,
0,1,1,1,1,1,
0,0,1,1,1,1,
0,0,0,-1,1,1,
0,0,0,0,0,1,
0,0,0,0,0,0,
};///0白 1黑 2空格
int i,j,t,x0,y0,a[6][6],ans;
int dx[9]={0,-2,-2,-1,-1,1,1,2,2};
int dy[9]={0,-1,1,-2,2,-2,2,-1,1};
int done()///完成
{
int id,jd,s=0;
for (id=1; id<=5; id++)
for (jd=1; jd<=5; jd++)
{
if (a[id][jd]!=m[id][jd]) s++;
}
return s;
}
void dfs(int x,int y,int sum,int last)///(x,y)空格 sum步数
{
int don=done();
if (sum+don>16) return;
else if (sum>=ans) return;
else if (don==0)
{ans=min(ans,sum);return;}
else
for (int k=1; k<=8; k++)
{
int tx=x+dx[k];
int ty=y+dy[k];
if (1<=tx&&tx<=5&&1<=ty&&ty<=5&&(k+last)!=9)///可以搜索
{
swap(a[tx][ty],a[x][y]);
dfs(tx,ty,sum+1,k);
swap(a[tx][ty],a[x][y]);
}
}
}
int main()
{
cin>>t;
for (int it=1; it<=t; it++)
{
ans=99999;
for (i=1; i<=5; i++)
{
string s;
cin>>s;
for (j=1; j<=5; j++)
{
if (s[j-1]=='1') a[i][j]=1;
else if (s[j-1]=='0') a[i][j]=0;
else if (s[j-1]=='*')
{
a[i][j]=-1;
x0=i;
y0=j;
}
}
}
dfs(x0,y0,0,0);
if (ans<=15) cout<<ans<<endl;
else cout<<"-1"<<endl;
}
return 0;
}
复制代码
作者:
张笑宇
时间:
2018-6-1 22:56
判断是否往回走的
(k+last)!=9
好巧妙
没有想到.......
作者:
YTC
时间:
2018-7-2 10:01
迭代加深
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
using namespace std;
const int dx[]={0,-2,-1,1,2,-2,-1,1,2};
const int dy[]={0,1,2,2,1,-1,-2,-2,-1};
const int p[6][6]=
{
+0,+0,+0,+0,0,0,
+0,+1,+1,+1,1,1,
+0,+0,+1,+1,1,1,
+0,+0,+0,-1,1,1,
+0,+0,+0,+0,0,1,
+0,+0,+0,+0,0,0,
};
int f[7][7];
const int base=10;
int T;
char c;
int stx,sty;
int v[1001];
int maxd;
bool ok;
int ans;
int rem()
{
int ans=0;
for(int i=1;i<=5;i++)
for(int j=1;j<=5;j++)
{
if(f[i][j]!=p[i][j]) ans++;
}
return ans;
}
void dfs(int a,int b,int last,int d)
{
if(d+rem()-1>maxd) return ;//至少走rem()-1步才能到
if(rem()==0)
{
ok=1;
return;
}
for(int i=1;i<=8;i++)
{
int x=a+dx[i];
int y=b+dy[i];
if(x<1||x>5||y<1||y>5||i+last==9) continue;
swap(f[a][b],f[x][y]);
dfs(x,y,i,d+1);
swap(f[a][b],f[x][y]);
}
}
int main()
{
cin>>T;
while(T--)
{
for(int i=1;i<=5;i++)
for(int j=1;j<=5;j++)
{
cin>>c;
if(c=='*')
{
f[i][j]=-1;
stx=i;
sty=j;
}
else f[i][j]=c-'0';
}
for(maxd=0;maxd<=15;maxd++)
{
ok=0;
dfs(stx,sty,0,0);
if(ok) {cout<<maxd<<endl;break;}
}
if(!ok) cout<<-1<<endl;
}
return 0;
}
复制代码
欢迎光临 华师一附中OI组 (http://hsyit.cn/)
Powered by Discuz! X3.2