码迷,mamicode.com
首页 > 其他好文 > 详细

UESTC_Just a Maze CDOJ 1162

时间:2015-06-17 14:42:03      阅读:97      评论:0      收藏:0      [点我收藏+]

标签:

Just a Maze

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 262144/262144KB (Java/Others)
 

Here is a maze with N × M room.

You start from the room (SR,SC) and want to go to the room located at (TR,TC). However, there are many traps and monsters in this maze.

There are 4 types of rooms:

1. Blank->(‘.‘). which has nothing.
2. Rock->(‘#‘). which you can not enter it.
3. Trap->(‘a‘~‘z‘), which once you enter it, you will suffer (Trap-‘a‘+1) damage(s). After you leave,the trap will reset so it can be triggered next time.
4. Monster->(‘A‘~‘Z‘). If you go into a monster room or any room adjacent to a monster room, the monster will immediately rush up to you and fight with you. You will kill it, but you will get hurt too, suffering (Monster-‘A‘+1) damage(s). And the monster will not revive.

Two rooms are adjacent if and only if they share an edge. You can take 1 step to go from a room to another adjacent room.

The safest path is a lowest total damage path. Among all safest path,find the path with lowest steps.

Input

The first line contains two integers N and M (1N,M500).

The second line contains 4 integers SR,SC,TR,TC (1SR,TRN and 1SC,TCM).

For the next N lines, each line contains M characters indicating the map of maze. Each type of room is marked as:

1. Blank->(‘.‘)
2. Rock->(‘#‘)
3. Trap: from ‘a‘~‘z‘
4. Monster: from ‘A‘~‘Z‘

The damage you suffer from the trap ‘a‘ is 1,‘b‘ is 2..and so on.

The damage you suffer from the monster ‘A‘ is 1... and ‘Z‘ is 26.

The room (SR,SC) and (TR,TC) are always blank rooms and will not be adjacent to any monster room.

Output

Output the lowest total damage and the lowest steps in all safest path.

Sample input and output

Sample InputSample Output
3 5
1 1 3 5
..b..
.zC#.
..a..
4 6

Source

2015 UESTC ACM Summer Training Team Selection (4)
 
解题报告:
 本题的难点在于如何建图,普通简图的话会受到多次伤害(就是怪物不死的问题)
因为有个条件是怪物不相邻,那么我们就给怪物所在的附近的 4 个格子全部建边(每个格子可以通往另外3个格子),同时我们知道这个时间代价是 2
处理好这个之后,我们考虑如何处理伤害的问题
我们定义Damge( i , j ) 表示从格子i 到 格子j所受的伤害(这个移动只能是相邻的或者通过上面建的边)
Damage(i ,j ) = Damge(j) - ( i , j )之间共享的怪兽的伤害
然后本题就完了
注意不要使用spfa,不要使用spfa,不要使用spfa,重要的事说三遍
请使用dijkstra的堆优化!!
 
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#define pb push_back
#define show(x) cout << "x is " << x << endl
#define printarray(x,n) for(int i = 0 ; i < n ; ++ i) x == 0 ? cout << x[i] : cout << x[i] << " ";cout << endl
#define input_fast std::ios::sync_with_stdio(false);std::cin.tie(0)
#define local freopen("in.txt","r",stdin)
#define loop(x,st,ed) for(int x = st ; x < ed ; ++ x)
#define blackkey
typedef long long ll;
using namespace std;
const int maxn = 500 + 50;

typedef struct status
{
  int x , y  ;
  status(int x, int y )
   {
      this->x = x, this->y = y ;
   }    
};

typedef struct Edge
{
  int x , y , co;
  Edge(int x, int y , int co)
   {
      this->x = x , this->y = y , this->co = co;
   }
};

typedef struct qst
{
  int x , y , d1 , d2;
  friend bool operator < (const qst & a , const qst & b)
   {
         if (a.d1 < b.d1)
          return false;
         else if(a.d1 == b.d1 && a.d2 < b.d2)
          return false;
         return true;
   }    
  qst(int x,int y,int d1,int d2)
   {
        this-> x = x , this->y = y , this->d1 = d1 , this->d2 = d2;
   }
};


typedef pair<int,int>pos;
typedef pair<pos,pos>spj;
int n , m , sr , sc , tr , tc , mincost[maxn][maxn][2] , dir[4][2] = {-1,0,1,0,0,1,0,-1} , damage[maxn][maxn] , ban[maxn][maxn] , damage2[maxn][maxn] ,used[maxn][maxn] ;  
char s[maxn][maxn];
vector<Edge>E[maxn][maxn];
set<spj>sb;
priority_queue<qst>q;

inline int inmap(int x,int y)
{
   return x <= n && x >= 1 && y <= m && y >= 1;
}

int GetSameDamage(int x1,int y1,int x2,int y2)
{
   int ans = 0;
   loop(i , 0 , 4)
    {
        int newx = x1 + dir[i][0];
        int newy = y1 + dir[i][1];
        if (s[newx][newy] <= Z && s[newx][newy] >= A)
         {
             loop(j , 0 , 4)
              if (x2 + dir[j][0] == newx && y2 + dir[j][1] == newy)
               {
                    ans += s[newx][newy] - A + 1;
                    break;
              }
         }
    }
   return ans;
}


void dijkstra()
{
  q.push(qst(sr,sc,0,0));
  memset(mincost,-1,sizeof(mincost));
  mincost[sr][sc][0] = mincost[sr][sc][1] = 0;
  while(!q.empty())
   {
         int x = q.top().x , y = q.top().y , d1 = q.top().d1 , d2 = q.top().d2 ; q.pop();
         if (used[x][y])
          continue;
         used[x][y] = 1;
         loop(i , 0 , 4)
         {
              int newx = x + dir[i][0] , newy = y + dir[i][1] ;
              if (!inmap(newx,newy) || ban[newx][newy]) continue;
             int newhurt = d1 + damage[newx][newy] + damage2[newx][newy] , newcost = d2 + 1;
             if ( newhurt < mincost[newx][newy][0] || !(mincost[newx][newy][0] ^ -1)  )
              {
                   mincost[newx][newy][0] = newhurt;
                   mincost[newx][newy][1] = newcost;
                   q.push(qst(newx,newy,newhurt,newcost));
              }
             else if( !(newhurt ^ mincost[newx][newy][0]) && newcost < mincost[newx][newy][1])
              {
                    mincost[newx][newy][1] = newcost;
                    q.push(qst(newx,newy,newhurt,newcost));
              }
         }
      loop(i , 0 , E[x][y].size() )
         {
              int newx = E[x][y][i].x , newy = E[x][y][i].y , add = E[x][y][i].co;
             int newhurt = d1 + damage[newx][newy] + damage2[newx][newy] -  add, newcost = d2 + 2;
             if ( newhurt < mincost[newx][newy][0] || !(mincost[newx][newy][0] ^ -1) )
              {
                   mincost[newx][newy][0] = newhurt;
                   mincost[newx][newy][1] = newcost;
                   q.push(qst(newx,newy,newhurt,newcost));
              }
             else if( !(newhurt ^ mincost[newx][newy][0]) && newcost < mincost[newx][newy][1])
              {
                    mincost[newx][newy][1] = newcost;
                    q.push(qst(newx,newy,newhurt,newcost));
              }
         }
   }
}


int main(int argc,char *argv[])
{
  //local;
  memset(damage , 0 , sizeof(damage));
  memset(damage2 , 0 , sizeof(damage2));
  memset(used,0,sizeof(used));
  scanf("%d%d%d%d%d%d",&n,&m,&sr,&sc,&tr,&tc);
  loop(i , 1 , n + 1)
   scanf("%s",s[i] + 1); 
  loop(i , 1 , n + 1)
   loop(j , 1 , m + 1)
    {
        if (s[i][j] == #)
         ban[i][j] = 1;
        else if (s[i][j] <= z && s[i][j] >= a)
         damage[i][j] = s[i][j] - a + 1;
        else if(s[i][j] <= Z && s[i][j] >= A)
         {
             ban[i][j] = 1;
             loop(k , 0 , 4)
              damage2[i + dir[k][0]][j + dir[k][1]] += s[i][j] - A + 1;
             loop(kx , 0 , 4)
              {
                  int newx = i + dir[kx][0] ;
                 int newy = j + dir[kx][1] ;
                 if (!inmap(newx,newy) || s[newx][newy] == #) continue;
                 pos p1(newx,newy);
                 loop(k2 , 0 , 4)
                  {
                     int tx = i + dir[k2][0];
                     int ty = j + dir[k2][1];
                     if ( !inmap(tx,ty) || s[tx][ty] == # || (tx ==newx && ty == newy)) continue;
                     pos p2(tx,ty);
                     spj ju = make_pair(p1,p2);
                     if (!sb.count(ju))
                      {
                          int co = GetSameDamage(newx,newy,tx,ty);
                          E[newx][newy].pb(Edge(tx,ty,co));
                          sb.insert(ju);
                      }
                     
                  }    
             }
         }
    }
  dijkstra();
  printf("%d %d\n",mincost[tr][tc][0],mincost[tr][tc][1]);
  return 0;
}

 

UESTC_Just a Maze CDOJ 1162

标签:

原文地址:http://www.cnblogs.com/Xiper/p/4582959.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!