POJ - 3592 - Instantaneous Transference

先上题目:

Instantaneous Transference
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 5461   Accepted: 1193

Description

It was long ago when we played the game Red Alert. There is a magic function for the game objects which is called instantaneous transfer. When an object uses this magic function, it will be transferred to the specified point immediately, regardless of how far it is.

Now there is a mining area, and you are driving an ore-miner truck. Your mission is to take the maximum ores in the field.

The ore area is a rectangle region which is composed by n × m small squares, some of the squares have numbers of ores, while some do not. The ores can't be regenerated after taken.

The starting position of the ore-miner truck is the northwest corner of the field. It must move to the eastern or southern adjacent square, while it can not move to the northern or western adjacent square. And some squares have magic power that can instantaneously transfer the truck to a certain square specified. However, as the captain of the ore-miner truck, you can decide whether to use this magic power or to stay still. One magic power square will never lose its magic power; you can use the magic power whenever you get there.

Input

The first line of the input is an integer T which indicates the number of test cases.

For each of the test case, the first will be two integers NM (2 ≤ NM ≤ 40).

The next N lines will describe the map of the mine field. Each of the N lines will be a string that contains M characters. Each character will be an integer X (0 ≤ X ≤ 9) or a '*' or a '#'. The integer X indicates that square hasX units of ores, which your truck could get them all. The '*' indicates this square has a magic power which can transfer truck within an instant. The '#' indicates this square is full of rock and the truck can't move on this square. You can assume that the starting position of the truck will never be a '#' square.

As the map indicates, there are K '*' on the map. Then there follows K lines after the map. The next K lines describe the specified target coordinates for the squares with '*', in the order from north to south then west to east. (the original point is the northwest corner, the coordinate is formatted as north-south, west-east, all from 0 to N - 1,- 1).

Output

For each test case output the maximum units of ores you can take.  

Sample Input

1
2 2
11
1*
0 0

Sample Output

3

Source

 
  题意:给你一幅地图(矩阵),地图上有的点有矿物,有的点是传送门,前面两种都可以走,有的点无法通过。从左上角(西北方)开始走,只可以向南或者向东走,每个位置的矿物只可以吃一遍,问你在这幅地图上走最多可以吃多少的矿物。
  分析:传送门可能回在地图上构成回路,所以一开始可以先缩点,重新构图,然后跑一边最长路就可以得出结果了。
  首先用Tarjan缩点,然后再用spfa跑一次最长路。
  感觉这一题比较坑的地方是构图,在网上看其他人的代码好像都是将二维转为一维,大概就140行~160行,结果我直接用二维来保存dfn,low等信息,写了快200行→_→。
  中间WA了几次,第一次是求最长路的时候用了dij,后来换成spfa就没事了,当时感觉缩点以后还有环,但是跟师兄讨论的时候发现缩点以后似乎剩下的是一个DAG,那样的话大概是dij写错了一点了···。还有就是对于判断某个可可以走的点下一步可以往那边走的时候,扫了判断是不是个坑,这里少了个判断的原因是一开始以为直接判断dfn就可以看出是不是个坑···结果WA了几次才发现还需要另外判断···。
  这应该是第二次用Tarjan,再有一点需要注意的是在元素退栈的时候需要标记元素已经不在栈里面了,否者会出错。这是因为在前面的步骤里面两个判断的条件并不是同一个条件,一个是判断子节点访问了没有,另一个是判断子节点在不在栈里面,所以如果没有清楚地标记元素是否在栈里的话就会多进行一些步骤同时结果会出错。
 
上代码:
 
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <stack>
  4 #include <queue>
  5 #define max(x,y) (x >= y ? x : y)
  6 #define min(x,y) (x <= y ? x : y)
  7 #define MAX 100
  8 using namespace std;
  9 
 10 int n,m,index,id;
 11 char map[MAX][MAX];
 12 int star[MAX*MAX];
 13 int starnum;
 14 int sy[MAX][MAX],sx[MAX][MAX];
 15 int dfn[MAX][MAX],low[MAX][MAX],belong[MAX][MAX];
 16 int val[MAX*MAX];
 17 stack<int> sty,stx;
 18 bool instack[MAX][MAX];
 19 int p[MAX*MAX];
 20 typedef struct{
 21     int to;
 22     int w;
 23     int next;
 24 }Edge;
 25 Edge e[MAX*MAX*3];
 26 int tot;
 27 int dist[MAX*MAX];
 28 int Max;
 29 
 30 void reset(){
 31     index=0;
 32     id=0;
 33     starnum=0;
 34     memset(map,0,sizeof(map));
 35     memset(sy,-1,sizeof(sy));
 36     memset(sx,-1,sizeof(sx));
 37     memset(dfn,-1,sizeof(dfn));
 38     memset(low,-1,sizeof(low));
 39     memset(belong,-1,sizeof(belong));
 40     while(!sty.empty()) sty.pop();
 41     while(!stx.empty()) stx.pop();
 42     memset(val,0,sizeof(val));
 43     memset(instack,0,sizeof(instack));
 44     memset(p,-1,sizeof(p));
 45     memset(e,0,sizeof(e));
 46     tot=0;
 47 }
 48 
 49 void add(int u,int v,int w){
 50     e[tot].next=p[u];   e[tot].to=v;    e[tot].w=w; p[u]=tot++;
 51 }
 52 
 53 void tarjan(int y,int x){
 54     dfn[y][x]=low[y][x]=index++;
 55     sty.push(y);
 56     stx.push(x);
 57     instack[y][x]=1;
 58 
 59     if(y+1<n && map[y+1][x]!='#' && dfn[y+1][x]==-1){
 60         tarjan(y+1,x);
 61         low[y][x]=min(low[y][x],low[y+1][x]);
 62     }else if(instack[y+1][x]){
 63         low[y][x]=min(low[y][x],dfn[y+1][x]);
 64     }
 65 
 66     if(x+1<m && map[y][x+1]!='#' && dfn[y][x+1]==-1){
 67         tarjan(y,x+1);
 68         low[y][x]=min(low[y][x],low[y][x+1]);
 69     }else if(instack[y][x+1]){
 70         low[y][x]=min(low[y][x],dfn[y][x+1]);
 71     }
 72 
 73     if(sy[y][x]!=-1){
 74         if(dfn[sy[y][x]][sx[y][x]]==-1){
 75             tarjan(sy[y][x],sx[y][x]);
 76             low[y][x]=min(low[y][x],low[sy[y][x]][sx[y][x]]);
 77         }else if(instack[sy[y][x]][sx[y][x]]){
 78             low[y][x]=min(low[y][x],dfn[sy[y][x]][sx[y][x]]);
 79         }
 80     }
 81 
 82     if(dfn[y][x]==low[y][x]){
 83         int yy,xx;
 84         id++;
 85         val[id]=0;
 86         do{
 87             yy=sty.top();
 88             xx=stx.top();
 89             sty.pop();
 90             stx.pop();
 91             belong[yy][xx]=id;
 92             instack[yy][xx]=0;
 93             val[id]+=( map[yy][xx]== '*' ? 0 : map[yy][xx]-'0');
 94         }while(y!=yy || x!=xx);
 95     }
 96 }
 97 
 98 void redraw(){
 99     for(int i=0;i<n;i++){
100         for(int j=0;j<m;j++){
101             int u,v;
102             u=belong[i][j];
103             if(i+1<n && belong[i+1][j]!=-1){
104                 v=belong[i+1][j];
105                 if(u!=v){
106                     add(u,v,val[v]);
107                 }
108             }
109 
110             if(j+1<m && belong[i][j+1]!=-1){
111                 v=belong[i][j+1];
112                 if(u!=v){
113                     add(u,v,val[v]);
114                 }
115             }
116 
117 
118             if(sy[i][j]!=-1 && belong[sy[i][j]][sx[i][j]]!=-1){
119                 v=belong[sy[i][j]][sx[i][j]];
120                 if(u!=v){
121                     add(u,v,val[v]);
122                 }
123             }
124 
125         }
126     }
127 }
128 
129 void spfa(int a){
130     bool vin[MAX*MAX]={0};
131     memset(dist,0,sizeof(dist));
132     queue<int> q;
133     while(!q.empty()) q.pop();
134     dist[a]=val[a];
135     Max=dist[a];
136     q.push(a);
137     vin[a]=1;
138     while(!q.empty()){
139         int u=q.front();
140         q.pop();
141         vin[u]=0;
142         for(int v=p[u];v!=-1;v=e[v].next){
143             if(dist[e[v].to]<dist[u]+e[v].w){
144                 dist[e[v].to]=dist[u]+e[v].w;
145                 if(!vin[e[v].to]){
146                     q.push(e[v].to);
147                     vin[e[v].to]=1;
148                 }
149                 Max=max(Max,dist[e[v].to]);
150             }
151         }
152     }
153 }
154 
155 int main()
156 {
157     int t;
158     //freopen("data.txt","r",stdin);
159     scanf("%d",&t);
160     getchar();
161     while(t--){
162         scanf("%d %d",&n,&m);
163         getchar();
164         reset();
165         for(int i=0;i<n;i++){
166             scanf("%s",map[i]);
167             for(int j=0;j<m;j++){
168                 if(map[i][j]=='*'){
169                     star[starnum++]=i*m+j;
170                 }
171             }
172         }
173         for(int i=0;i<starnum;i++){
174             int y,x;
175             scanf("%d %d",&y,&x);
176             getchar();
177             if(map[y][x]!='#'){
178                 sy[star[i]/m][star[i]%m]=y;
179                 sx[star[i]/m][star[i]%m]=x;
180             }
181         }
182         for(int i=0;i<n;i++){
183             for(int j=0;j<m;j++){
184                 if(map[i][j]!='#' && dfn[i][j]==-1){
185                     tarjan(i,j);
186                 }
187             }
188         }
189         redraw();
190         spfa(belong[0][0]);
191         printf("%d\n",Max);
192     }
193     return 0;
194 }
3592

 

 

posted @ 2014-03-12 21:34  海拉鲁的林克  阅读(223)  评论(0编辑  收藏  举报