题目地址:http://poj.org/problem?id=1324
写了一天了 ,一开始想表示状态用头和尾位置,但很快写出来就WR
然后就用根据贪吃蛇的节点与上一个节点位置关系保存状态,一共有4个状态,上下左右,0~3表示,正好二进制占两个位
最多有14个状态,所以int就可以保存
然后写出来后MLE然后TLE然后MLE然后TLE然后WR.... 不容易啊woc...
最后发现vector太慢了,果断用数组,再重写一遍
然后发现h()定义有很大问题,再改
还有不同h()计算方式不行,h()一定要体现h()+g()最小离终点最近,这样才会正确
所以单单把h()*100是不行的,因为有种可能会导致h()小但g()很大的排在队列前面
h()定义法则如下:
我选的是以头节点离终点的曼哈顿距离为h(), 这样肯定相容
代码如下:23864K 1672MS
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int maxn=20+5;
struct Node{
int x,y,snack,f,g,h;
Node(int x=0,int y=0,int s=0,int g=0,int h=0):x(x),y(y),snack(s),f(g+h),g(g),h(h){}
bool operator < (const Node& n) const {
if(f==n.f) return g>n.g;
return f>n.f;
}
};
struct Snack{
int x[10],y[10];
};
bool closed[maxn][maxn][1<<15];
int R,C,m;
bool G[maxn][maxn];
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
int H(const Snack& s){
int cnt=0;
// for(int i=0;i<m;i++)
// cnt+=(s.x[i]+s.y[i])*i*100; //头的比重大
cnt+=s.x[0]+s.y[0];
return cnt*100;
}
bool inside(int x,int y){
return x>=1&&x<=R&&y>=1&&y<=C;
}
int Encode(const Snack& s){
int code=0;
for(int i=m-1;i>=1;i--){
int xt=find(dx,dx+4,s.x[i]-s.x[i-1])-dx;
int yt=find(dy,dy+4,s.y[i]-s.y[i-1])-dy;
int t=max(xt,yt);
code<<=2; code|=t;
}
return code;
}
Snack Decode(int x,int y,int s){
Snack ns;
ns.x[0]=x,ns.y[0]=y;
for(int i=1;i<m;i++){
int t=3; t&=s;
ns.x[i]=ns.x[i-1]+dx[t];
ns.y[i]=ns.y[i-1]+dy[t];
s>>=2;
}
return ns;
}
Node move(Node s,int i){ //i=up down left right
int x=s.x+dx[i];
int y=s.y+dy[i];
int t=i^1; //反方向
int snack=s.snack;
snack<<=2; snack|=t;
snack&=((1<<((m-1)*2))-1); //去掉最高位
int h=H(Decode(x,y,snack));
return Node(x,y,snack,s.g+1,h);
}
bool bCross(int x,int y,int s,int i){
int nx=x+dx[i];
int ny=y+dy[i];
if(!inside(nx,ny)||G[nx][ny]) return false;
Snack snack=Decode(x,y,s);
for(int i=1;i<m;i++)
if(nx==snack.x[i]&&ny==snack.y[i]) return false;
return true;
}
bool inClosed(Node s){
if(closed[s.x][s.y][s.snack]) return true;
closed[s.x][s.y][s.snack]=true;
return false;
}
int A_star(Node start)
{
memset(closed,false,sizeof(closed));
priority_queue<Node> open;
open.push(start);
inClosed(start);
while(!open.empty())
{
Node s=open.top(); open.pop();
if(s.x==1&&s.y==1) return s.g;
for(int i=0;i<4;i++)
{
if(!bCross(s.x,s.y,s.snack,i)) continue;
Node ns=move(s,i);
if(inClosed(ns)) continue;
else open.push(ns);
}
}
return -1;
}
int main()
{
int n,x,y,kase=0; Snack snack;
while(scanf("%d%d%d",&R,&C,&m)!=EOF)
{
if(R==0&&C==0&&m==0) break;
for(int i=0;i<m;i++){
scanf("%d%d",&x,&y);
snack.x[i]=x;
snack.y[i]=y;
}
scanf("%d",&n);
memset(G,false,sizeof(G));
for(int i=0;i<n;i++){
scanf("%d%d",&x,&y);
G[x][y]=true;
}
Node s=Node(snack.x[0],snack.y[0],Encode(snack),0,H(snack));
printf("Case %d: %d\n",++kase,A_star(s));
}
return 0;
}