Treasure HuntingTime
limit:4000/2000 MS (java/others) Memory limit:131072/65536 K (java/others)
Total submission (s): 1532 Accepted Submission (s): 400
Problem Descriptiondo You like treasure hunting? Today, with one of its friend, ISea is on a venture trip again. As most of the movie said, they find so many gold hiding on their trip.
Now ISea's clever friend have already got the map of the place they is going to hunt, simplify the map, there is three GR Ound types:
'. ' means blank ground, they can get through it
' # ' means block, they can ' t get through it
' * ' means gold hiding under ground, also they can just get through it (but do you won ' t, right?)
What makes ISea very delighted are the friend with him are extraordinary justice, he would not take away things which doesn ' T belong to him, so all the treasure belong to ISea oneself!
But his friend had a request, he would set up a number of rally points on the map, namely ' a ', ' B ' ... ' Z ', ' A ', ' B ' ... ' Z ' (in this order, but may is less than), they start in ' A ', each time friend reaches to the next rally point in the S Hortest, they has to meet here (i.e. ISea reaches there earlier than or same as he friend), then start together, but You can choose different paths. Initially, ISea ' s speed was the same with his friend, but to grab treasures, he save one time unit among each part of the road, He use the only one unit to get a treasure, after being picked, the treasure's point change into blank ground.
Under the premise of his friend's rule, how much treasure ISea can get on most?
Inputthere is several test cases in the input.
Each test case is begin with the integers R, C (2≤r, c≤100), indicating the row number and the column number.
Then R strings follow with each string have C characters (must be ' a ' – ' Z ' or ' a ' – ' Z ' or '. ' or ' "or ' * '), indicating the Type in the coordinate.
The input terminates by end of file marker.
Outputfor each test case, output one integer, indicating maximum gold number ISea can get, if they can ' t meet at one or mo Re rally points, just output-1.
Sample Input
2 4A. B.***C2 4a#b.***c
Sample Output
12
Authorisea @ whu
Source2010 acm-icpc multi-university Training Contest (3)--host by WHU
The main idea: Isea and his friends to find treasure, the map shows a lot of gold coins, the picture has the letter ' A ', ' B ' ... ' Z ', ' A ', ' B ' ... ' Z ', indicating their rendezvous point each time, starting position in a, his friend each time at the shortest distance there is a rendezvous point to the next rendezvous place, Isea must also take the shortest way, but he can choose to walk with gold coins Road, but he only one unit of time can get gold coins, that is, each time the rendezvous process, He can only take a piece of gold. Q: At the final rendezvous point, Isea can earn as many coins as possible. Output-1:1. The letters that exist are not contiguous. 2. From a cannot reach all occurrences of the letter.
The process of building the map:
First, record the location of the letters and treasures, and count and label them.
Each gold position label is set to P1, the starting point of each rendezvous is set to P2, the source S, the meeting point T
The following three types of edges can be built: <u, V, w>, respectively, representing the starting point, end point, and edge right of an edge.
1. <s, p2, 1> says that each departure has a maximum of 1 gold coins.
2. <p2, p1, 1> said that each departure can get the shortest path of any one gold
3. <p1, T, 1> says to take a gold coin from each coin position
Such a map, you can ensure maximum flow, ISEA get the most gold coins, of course, in line with the rules.
The question is also a key point: the 2nd of the building map. How to get from the beginning of the road to the next destination, the shortest path through the location of the treasure (the bad will time out). First BFS, each letter to reach all points of the shortest distance vist[letter [arrival position] to find out, if satisfied: vist[start letter [Treasure location]+vist[target letter] [the location of the same treasure]==vist[the starting letter] [Target letter position], It means the treasure is on the shortest way.
This question can also be done with the maximum matching of the binary graph. Relative to my above diagram, remove the source point s, meeting point T, can be. The P2 composed of x set and P1 composed of y set, on the topic, each starting point to get a gold coin, to obtain the maximum number of coins, just in line with the definition of the maximum matching binary graph.
#include <stdio.h> #include <string.h> #include <queue> #include <algorithm>using namespace std ; #define Captype intconst int maxn = 100010; Total number of points const int MAXM = 400010; Total number of edges const int INF = 1<<30;struct edg{int to,next; Captype Cap,flow;} Edg[maxm];int Eid,head[maxn];int GAP[MAXN]; The number of points for each distance (or can be considered a height) int DIS[MAXN]; The shortest distance from each point to the end Enode int CUR[MAXN]; Cur[u] indicates that from the U point can flow through the cur[u] number side int pre[maxn];void init () {eid=0; memset (head,-1,sizeof (Head));} There are three parameters to the edge, 4 parameters void addedg (int u,int v,captype c,captype rc=0) without a forward edge {edg[eid].to=v; edg[eid].next=head[u]; Edg[eid].cap=c; edg[eid].flow=0; head[u]=eid++; Edg[eid].to=u; EDG[EID].NEXT=HEAD[V]; EDG[EID].CAP=RC; edg[eid].flow=0; head[v]=eid++;} Captype maxflow_sap (int snode,int enode, int n) {//n is the total number of points including the source and sink points, this must be noted memset (Gap,0,sizeof (GAP)); memset (dis,0,sizeof (dis)); memcpy (cur,head,sizeof (head)); Pre[snode] =-1; Gap[0]=n; Captype ans=0; Max Stream int U=snode; while (Dis[snoDe]<n) {//Judging from the snode point there is no flow to the next adjacent point if (u==enode) {//Find a way to increase the flow captype min=inf; int inser; for (int i=pre[u]; i!=-1; i=pre[edg[i^1].to])//To find the maximum amount of traffic Min if (min>edg[i].cap-edg[i].flow) { Min=edg[i].cap-edg[i].flow; Inser=i; } for (int i=pre[u]; i!=-1; i=pre[edg[i^1].to]) {edg[i].flow+=min; Edg[i^1].flow-=min; Flow of the side that can be recycled} ans+=min; u=edg[inser^1].to; Continue } bool flag = FALSE; It is possible to determine whether an int v can flow toward the neighboring point from the U point; for (int i=cur[u]; i!=-1; i=edg[i].next) {v=edg[i].to; if (edg[i].cap-edg[i].flow>0 && dis[u]==dis[v]+1) {flag=true; Cur[u]=pre[v]=i; Break }} if (flag) {u=v; Continue }//If a flow adjacent point is not found above, then the distance from the starting point U (which can also be considered a height) is the minimum distance of the adjacent flow point +1 intmind= N; for (int i=head[u]; i!=-1; i=edg[i].next) if (edg[i].cap-edg[i].flow>0 && mind>dis[edg[i].to]) { MIND=DIS[EDG[I].TO]; Cur[u]=i; } gap[dis[u]]--; if (gap[dis[u]]==0) return ans; When Dis[u] The point of this distance is gone, it is impossible to find an augmented stream path from the source point//Because there is only one distance from the sink point to the current point, then from the source point to the sink point must pass the current point, but the current point is not able to find Can flow to the point, then the inevitable flow of dis[u]=mind+1;//if a stream of adjacent points is found, the distance is the distance of the adjacent point +1, if not found, then the n+1 gap[dis[u]]++; if (U!=snode) u=edg[pre[u]^1].to; Return an Edge} return ans; int vist[55][10005], dir[4][2]={1,0,-1,0,0,1,0,-1}; char mapt[105][105];void bfs (int s,int frome,int R,int C) {QUEUE&L t;int>q; int x, y; vist[s][frome]=0; Q.push (Frome); while (!q.empty ()) {int pre= q.front (); Q.pop (); x=pre/c; y=pre%c; for (int e=0; e<4; e++) {int tx=x+dir[e][0]; int ty=y+dir[e][1]; int now=tx*c+ty; if (tx>=0&&tx<r&&ty>=0&&ty<c&&vist[s][now]==-1&&mapt[tx][ty]!= ' # ') {vist[s][now]=vist[s][pre]+1; Q.push (now); }}}}int Main () {int id[105][105], idk, ch[100], gold[10005], GK, R, C; while (scanf ("%d%d", &r,&c) >0) {for (int i=0; i<r; i++) scanf ("%s", Mapt[i]); idk = GK = 0; memset (ch,-1,sizeof (ch)); for (int i=0, i<r; i++) for (int j=0; j<c; J + +) if (mapt[i][j]== ' * ') id[i][ J]=++IDK, Gold[gk++]=i*c+j; else if (mapt[i][j]>= ' a ' &&mapt[i][j]<= ' Z ') id[i][j]=++idk, ch[mapt[i][j]-' a ']=i*c+j; else if (mapt[i][j]>= ' a ' &&mapt[i][j]<= ' z ') id[i][j]=++idk, ch[mapt[i][j]-' a ' +26 ]=i*c+j; int ans = 0, snode=0, enode= idk+1; --------------------------------Building a map------------------------------------------- Init (); for (int i=0, i<r; i++) for (int j=0; j<c; J + +) if (mapt[i][j]>= ' A ' &&mapt[i][j]< ; = ' Z ' | | Mapt[i][j]>= ' a ' &&mapt[i][j]<= ' Z ') addedg (SNode, id[i][j], 1); Source point and destination build an edge else if (mapt[i][j]== ' * ') with a capacity of 1 {addedg (id[i][j], enode, 1); Treasure and meeting Point build a 1-size side} int i, j=51, Frome, to; while (ch[j]==-1&&j>=0) j--; j + +; memset (vist,-1,sizeof (vist)); for (i=0; i<j; i++)//first calculates the shortest distance if (ch[i]!=-1) BFS (i,ch[i],r,c) where each destination can reach; else{ans=-1; break; } if (ans==-1) {printf (" -1\n"); continue; } for (i=0; i<j-1; i++) {frome = ch[i]; to = ch[i+1]; if (vist[i][to]==-1) {ans =-1; } for (int e=0; e<gk; e++) if (vist[i][gold[e]]+vist[i+1][gOld[e]]==vist[i][to]) addedg (id[frome/c][frome%c], id[gold[e]/c][gold[e]%c], 1); The starting bit of each destination and each treasure on the shortest path is built with a capacity of 1 side}//--------------------------------------------------------------------- --------if (ans==0) {ans = Maxflow_sap (snode,enode,enode+1); } printf ("%d\n", ans); }}
HDU 3468 Treasure Hunting (Max stream sap) Classic (seemingly wide search for the largest stream)