[4.27] T4 eresalas treasure hunt

Posted by icecube on Thu, 21 Nov 2019 18:24:26 +0100

The main idea of the topic

You see the treasure not far in front of you. But you can't rush forward, because there is a strong magic border on the road.

These boundaries are divided into PPP types according to different energy. When you step into each kind of boundary, you will be hurt to some extent. In order to get the treasure, these injuries are nothing. But you need to minimize the damage.

Please design a route so that you can get the treasure through the border with the least damage. The boundary is a square with PPP different energies inside. Each letter represents one energy. You start at the top, and each time you can go to the adjacent position of your position, or transfer freely in the same energy boundary. Repeated entry into the same energy barrier will not be harmed again.

Topic analysis

Method 1:

Direct wide search is OK

Preprocessing coordinates of all the same energy junctions

Starting from the top layer, update the minimum damage value down to the position (i,j)(i,j)(i,j)

Find the minimum value KKK on the lowest layer

If K & lt; HK & lt; HK < H, output H − KH-KH − K. Otherwise output nono

Method two:
Since the same kind of border can be transmitted at will, and will not be hurt again, we might as well shrink the same kind of border into a unit.
Because you can only step into adjacent cells, you only need to consider the relationship between the shrunk cells.
Describe it with pictures. On this basis, we add a super source and super sink to represent the starting point and the location of the treasure.

We give each vertex a weight, which is the damage value of stepping into this kind of boundary.
The minimum damage received from getting the treasure from the starting point is to seek the minimum point weight from super source 000 to super sink P+1P+1P+1

Point weighted undirected graph is transformed into edge weighted digraph. In addition to the edges connecting the super source and super sink, each edge becomes two directed edges, and the edge weight is the origin weight of the vertex pointed by the directed edge.

Find the shortest circuit

Code

Code for method one

#include<bits/stdc++.h>
using namespace std;
struct A
{
	int x,y;
};
int n,p,h,ans=1e9;
int a[3005],mapa[55][55],f[55][55],fx[4][2]={{0,1},{1,0},{-1,0},{0,-1}};
bool vis[55][55];
vector<A> b[3005];
queue<A> q;
int main()
{
	memset(f,0x3f,sizeof(f));
	int M=f[0][0];
	scanf("%d%d%d",&n,&p,&h);
	for(int i=1;i<=p;i++)
	 scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)
	 for(int j=1;j<=n;j++)
	  scanf("%d",&mapa[i][j]),b[mapa[i][j]].push_back((A){i,j});
	for(int i=1;i<=n;i++)
	 if(!vis[1][i])
	 {
	   for(int j=0;j<b[mapa[1][i]].size();j++)
	   {
	   	 f[b[mapa[1][i]][j].x][b[mapa[1][i]][j].y]=a[mapa[1][i]];
	   	 vis[b[mapa[1][i]][j].x][b[mapa[1][i]][j].y]=1;
	   	 q.push((A){b[mapa[1][i]][j].x,b[mapa[1][i]][j].y});
	   }
	 }
	while(!q.empty())
	{
	  A ff;
	  ff=q.front();q.pop();
	  vis[ff.x][ff.y]=0;
	  int x,y;
	  for(int i=0;i<4;i++)
	  {
	  	x=ff.x+fx[i][0];y=ff.y+fx[i][1];
	  	if(x<1||x>n||y<1||y>n) continue;
	  	if(f[x][y]>a[mapa[x][y]]+f[ff.x][ff.y])
	  	{
	  	  for(int j=0;j<b[mapa[x][y]].size();j++)
	  	  {
	  	  	if(f[b[mapa[x][y]][j].x][b[mapa[x][y]][j].y]>a[mapa[x][y]]+f[ff.x][ff.y])
	  	  	{
	  	  	  f[b[mapa[x][y]][j].x][b[mapa[x][y]][j].y]=a[mapa[x][y]]+f[ff.x][ff.y];
	  	  	  if(vis[b[mapa[x][y]][j].x][b[mapa[x][y]][j].y]==0)
	   	 	  {
	   	 	    vis[b[mapa[x][y]][j].x][b[mapa[x][y]][j].y]=1;
	   	 	    q.push((A){b[mapa[x][y]][j].x,b[mapa[x][y]][j].y});
	   	 	  }
	  	  	}
	  	  }
	  	}
	  }
	}
	for(int i=1;i<=n;i++)
	 ans=min(ans,f[n][i]);
  	if(h>ans) printf("%d",h-ans);
  	else printf("NO");
	return 0;
}