HDU 3955 March【读题困难的BFS/PFS】

链接:http://acm.hdu.edu.cn/showproblem.php?pid=3955
这题的《Civilization》背景导致不少没玩过这款经典游戏的acmer悲剧了。这。。。表示还好没被读题坑了。。。不过敲着敲着就发现一处关键点没处理的时候感觉实在是太蛋疼了。。。果然这种比较恶心的题,要先设计好状态再开搞才是正确策略。

100*100的有限制地图,给一个起点,给一个终点,给一个行动值,问最小回合数是多少。
行动值和回合数:当行动值为0时结束回合,到下一回合。特例是,如果所剩行动值不为0但是小于任何移动所需的行动值,则可以强行行动,然后行动值归零。
地图限制:
用读入的数字来解析地图上的每一点,分为有/无森林,有/无敌人,是/否敌人占领区,六向有/无河等几种状态。
搜索的时候,注意条件的优先级:
首先判断是否敌人,如果是,则该点不可访问;
其次判断是否为敌占区(敌人周围6格),如果当前点和到达点都是敌占区(另外一个标记数组来记),那么只要移动,行动值就清零。
再判断是否道路,如果当前点和到达点都有道路(另外一个标记数组来记),那么移动花费只有0.25.
再判断有无河流,如果前往方向有何流,则行动值清零。
最后判断地形,根据有无森林判断是耗费1还是2行动值。

这个题目的要点就这些。说一下自己被坑的地方。
由于,道路和敌占区都要相连才能起作用,所以单独的这两者都是没用的,需要按照其原来状态标记,所以这两种情况需要另开标记数组来标记。
还有地图的优先级,记得低优先级的情况不要把高优先级的情况覆盖掉(比如不要用森林什么的覆盖掉敌人或者敌占区。。)
最后是搜索的时候,不要犯2.。。我今天写了个”加枝搜索“,自2了。。。
初始值是全部inf,出发点为1(为1啊少年!)。
搜索更新状态的时候,turn(回合数)因为和往常的普通bfs不同,可以不用+1(只要在出队的时候判断是否需要加1即可);
但是不能把MP值做相同的处理,如果【当前状态+转移】比【目标状态】更优的话,一定要用【当前状态+转移】更新【目标状态】。。而非【当前状态】自身。。
这个就是TLE和AC的关键差别啊~~!我了个去~!~!!!!

这道题用Priority First Search(PFS)比BFS要快一点。
我一开始还以为是状态转移过程中参量太多导致了TLE,所以把int和double都改成了short和float。好吧,我是个2B.今天我蒟蒻了。
啊啊啊啊啊啊啊。


#include <iostream>
#include <cstdio>
#include <cstring>
#include 
<cmath>
#define maxn 105
using namespace std;
const short inf = 20000;
bool con[maxn][maxn][7];
int mat[maxn][maxn];
bool road[maxn][maxn];
bool zoc[maxn][maxn];
int n,m,MP;
int stx,sty,enx,eny;
const double eps = 1e-6;
int comp(double x)
{
    
if(fabs(x) < eps)
        
return 0;
    
else if(x < -eps)
        
return -1;
    
else
        
return 1;
}
struct status
{
    
short x,y,turn;
    
float mp;
    status(){}
    status(
short _x,short _y,float _m,short _t):x(_x),y(_y),mp(_m),turn(_t){}
};
bool operator < (const status a,const status b)
{
    
return (a.turn > b.turn || (a.turn == b.turn && comp(a.mp - b.mp) < 0));
}
struct dist
{
    
short turn;
    
float mp;
    dist(){}
    dist(
float _m,int _t):turn(_t),mp(_m){}
} dis[maxn][maxn];
/*
6 nw
5 w
4 sw
3 se
2 e
1 ne
*/
char dx1[] = {0,-1,0,1,1,0,-1};//even
char dy1[] = {0,1,1,1,0,-1,0};
char dx2[] = {0,-1,0,1,1,0,-1};//odd
char dy2[] = {0,0,1,0,-1,-1,-1};
bool check(int x,int y)
{
    
return (1 <= x && x <= n && 1 <= y && y <= m);
}
void bfs()
{
    priority_queue 
<status> Q;
    Q.push(status(stx,sty,MP,
1));
    dis[stx][sty] 
= dist(MP,1);
    
while(!Q.empty())
    {
        status now 
= Q.top();
        Q.pop();
        
if(now.x == enx && now.y == eny)
            
break;
        
if(comp(now.mp) <= 0)
        {
            now.mp 
= MP;
            now.turn 
++;
        }
        
for(int i = 1;i <= 6;i++)
        {
            
int x,y;
            
if(now.x % 2 == 0)
            {
                x 
= now.x + dx1[i];
                y 
= now.y + dy1[i];
            }
            
else
            {
                x 
= now.x + dx2[i];
                y 
= now.y + dy2[i];
            }
            
float pm = now.mp;
            
if(!check(x,y) || mat[x][y] == 3)
                
continue;
            
else if(zoc[x][y] == 1 && zoc[now.x][now.y] == 1)
            {
                
if(dis[x][y].turn > now.turn || (dis[x][y].turn == now.turn && comp(dis[x][y].mp) < 0))
                {
                    Q.push(status(x,y,
0,now.turn));
                    dis[x][y] 
= dist(0,now.turn);
                }
            }
            
else if(road[x][y] == true && road[now.x][now.y] == true)
            {
                
if(dis[x][y].turn > now.turn || (dis[x][y].turn == now.turn && comp(dis[x][y].mp - (pm - 0.25)) < 0))
                {
                    Q.push(status(x,y,pm 
- 0.25,now.turn));
                    dis[x][y] 
= dist(pm - 0.25,now.turn);
                }
            }
            
else if(con[now.x][now.y][i] == 1)
            {
                
if(dis[x][y].turn > now.turn || (dis[x][y].turn == now.turn && comp(dis[x][y].mp) < 0))
                {
                    Q.push(status(x,y,
0,now.turn));
                    dis[x][y] 
= dist(0,now.turn);
                }
            }
            
else if(mat[x][y] == 1)
            {
                
if(dis[x][y].turn > now.turn || (dis[x][y].turn == now.turn && comp(dis[x][y].mp - (pm - 2)) < 0))
                {
                    Q.push(status(x,y,pm 
- 2,now.turn));
                    dis[x][y] 
= dist(pm - 2,now.turn);
                }
            }
            
else if(mat[x][y] == 0)
            {
                
if(dis[x][y].turn > now.turn || (dis[x][y].turn == now.turn && comp(dis[x][y].mp - (pm - 1)) < 0))
                {
                    Q.push(status(x,y,pm 
- 1,now.turn));
                    dis[x][y] 
= dist(pm - 1,now.turn);
                }
            }
        }
    }
}
/*
0 cost 1
1 cost 2
3 can't
*/
void fuck(int x,int y)
{
    
for(int i = 1;i <= 6;i++)
    {
        
if(x % 2 == 0 && check(x + dx1[i],y + dy1[i]))
            zoc[x 
+ dx1[i]][y + dy1[i]] = true;
        
else
        {
            
if( check(x + dx2[i],y + dy2[i]))
                zoc[x 
+ dx2[i]][y + dy2[i]] = true;
        }
    }
}

void gao()
{
    scanf(
"%d %d %d",&n,&m,&MP);
    
for(int i = 1;i <= n;i++)
        
for(int j = 1;j <= m;j++)
        {
            road[i][j] 
= 0;
            mat[i][j] 
= -1;
            zoc[i][j] 
= 0;
        }
    
for(int i = 1;i <= n;i++)
        
for(int j = 1;j <= m;j++)
        {
            
int opt;
            scanf(
"%d",&opt);
            
for(int k = 9;k >= 0;k--)
            {
                
if(opt >= (1 << k))
                {
                    opt 
-= (1 << k);
                    
if(k > 3)
                        con[i][j][k 
- 3= true;
                    
else
                    {
                        
if(k == 3)
                        {
                            mat[i][j] 
= 3;
                            fuck(i,j);
                        }
                        
else
                        {
                            
if(mat[i][j] == -1)
                                mat[i][j] 
= k;
                            
if(mat[i][j] == 2)
                            {
                                mat[i][j] 
= k;
                                road[i][j] 
= true;
                            }
                        }
                    }
                }
                
else
                {
                    
if(k > 3)
                        con[i][j][k 
- 3= false;
                }
            }
        }
    
for(int i = 1;i <= n;i++)
        
for(int j = 1;j <= m;j++)
            dis[i][j] 
= dist(0,inf);
    scanf(
"%d %d %d %d",&stx,&sty,&enx,&eny);
    stx
++;
    sty
++;
    enx
++;
    eny
++;
    bfs();
    
int ans = dis[enx][eny].turn;
    printf(
"%d\n",(ans == inf?-1:ans));
}
int main()
{
    
int t;
    scanf(
"%d",&t);
    
for(int i = 1;i <= t;i++)
    {
        printf(
"Case %d: ",i);
        gao();
    }
}

posted on 2011-08-18 19:46 BUPT-[aswmtjdsj] @ Penalty 阅读(458) 评论(0)  编辑 收藏 引用 所属分类: HDU Solution Report 搜索


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2011年8月>
31123456
78910111213
14151617181920
21222324252627
28293031123
45678910

导航

统计

常用链接

留言簿(1)

随笔分类(150)

随笔档案(71)

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜