noip 2010 water diversion into the city (dfs + greed)

Keywords: PHP

I'm very sorry, because I was a little busy yesterday, I didn't write the solution to this problem. I'll make it up today and try to write in more detail so that you can understand it.

Look at the meaning of the title:

In a distant country, there are beautiful lakes on one side and endless deserts on the other. The administrative division of the country is very special. It just forms a rectangle of NNN rows * M times M * M columns. As shown in the figure above, each grid represents a city, each city has an elevation.

In order to make the lake water as clear as possible for residents, water conservancy facilities are now being built in some cities. There are two kinds of water conservancy facilities: water storage plant and water conveyance station. The function of a water storage plant is to pump water from a lake into a reservoir in the city.

Consequently, only the 111th row of cities adjacent to the lake can construct water storage plants. The function of the water conveyance station is to transport the lake water from high to low by utilizing the height drop of the water conveyance pipeline. Therefore, the premise for a city to build a water conveyance station is that there are adjacent cities with higher elevation and public side, and water conservancy facilities have been built. Because the city of NNN line is close to desert and arid area of the country, water conservancy facilities are required in every city. So, can this requirement be met? If so, please calculate the minimum number of water storage plants to be built; if not, calculate the number of cities in arid regions where water conservancy facilities are impossible to build.

Input and output format

Input format:

Two numbers per row, separated by a space. The first line of input is two positive integers N,MN,MN,M, representing the size of the rectangle. Next, NNN rows, each row with MMM positive integers, represent the elevation of each city in turn.

   Output format:

Two lines. If the requirements can be met, the first line of output is an integer 111, the second line is an integer, representing the construction of at least several water storage plants; if the requirements can not be met, the first line of output is an integer 000, and the second line is an integer, representing that several cities in arid regions can not build water conservancy facilities.

This time I have taken up all the topics, Luogu has this problem, so you can go to Luogu and other oj to see the topics and test data, here is not much to say, mainly to talk about ideas.

From the data range of this question, n and m<=500 are very large, so we need to consider efficient algorithms, otherwise it will not be easy to overtime. This question says that water can flow from high to high, and then find out the least constructed water storage plant.

If not, output `0'... (still look at the meaning of the topic, the meaning of the topic is very clear).

It is not difficult to find that we must know that cities on lakes can flow there as water storage plants, which requires dfs to solve, and dfs also requires skills to record current locations that can be transported to cities near deserts.

In this way, we can get the relationship between Lake cities and desert cities and simplify the problem. If we look at the desert cities corresponding to Lake cities, we can see that the desert cities corresponding to Lake cities must be continuous (think, why?) if not continuous.

So there is no solution, we need to export the number of cities that can not be irrigated. For continuous cities, we can not easily think of the problem of interval coverage in greed. We need to sort the intervals, first ranking the left (small left front).

Look at the right side the same way on the left (the big front on the right), which is different from the order of interval selection (this is important, otherwise we can not get the optimal solution), and then do it according to the interval coverage scheme. You can go to the upper intervals of other blogs.

The explanation of coverage is not difficult, and then corresponds to this question, about the problem of interval coverage, I will say later, the following is the code:

 

// P1514 
// dfs + greedy(Interval Covering Problem)
#include <cstdio> 
#include <cstring> 
#include <algorithm>
using namespace std; 

const int maxn = 500 + 5;
int N, M, G[maxn][maxn]; 

int L[maxn][maxn], R[maxn][maxn]; // among L[1]Table 1 The leftmost desert city corresponding to the first city near the lake  
bool Vis[maxn][maxn], C[maxn];

const int dx[] = {-1, 1, 0, 0}; 
const int dy[] = {0, 0, -1, 1}; 

void dfs(int x, int y) {
  if (x == N-1) C[y] = 1; 
  for (int i = 0; i < 4; ++i) {
    int x1 = x + dx[i], y1 = y + dy[i]; 
    if (x1 >= 0 && x1 < N && y1 >= 0 && y1 < M && G[x][y] > G[x1][y1]) {
      if (Vis[x1][y1] == 0) {
        Vis[x1][y1] = 1; 
        dfs(x1, y1);
      }
      if (L[x][y] == -1 || (L[x][y] > L[x1][y1] && L[x1][y1] != -1)) L[x][y] = L[x1][y1]; 
      if (R[x][y] == -1 || (R[x][y] < R[x1][y1] && R[x1][y1] != -1)) R[x][y] = R[x1][y1]; 
    }
  }
}

int City[maxn];

bool cmp(int a, int b) {
  if (L[0][a] != L[0][b]) return L[0][a] < L[0][b]; 
  return R[0][a] > R[0][b];     
}

void find_pos(int& lastpos, int& rpos) {
  int larpos = 0, rem = rpos; 
  for (int i = rem; i < M; ++i) 
    if (L[0][City[i]] <= lastpos+1) {
      if (R[0][City[i]] > larpos) {
        larpos = R[0][City[i]]; 
        rpos = i;
      }
    }     
    else break; 
  lastpos = larpos; 
}

int main() { 
  freopen("in.txt", "r", stdin);
  freopen("out.txt", "w", stdout); 
  scanf("%d%d", &N, &M); 
  for (int i = 0; i < N; ++i) 
    for (int j = 0; j < M; ++j) 
      scanf("%d", &G[i][j]); 
  memset(L, -1, sizeof(L)); 
  memset(R, -1, sizeof(R));
  // dfs
  memset(Vis, 0, sizeof(Vis));
  for (int j = 0; j < M; ++j) L[N-1][j] = R[N-1][j] = j;
  for (int j = 0; j < M; ++j) if (!Vis[0][j]) {
    Vis[0][j] = 1; 
    dfs(0, j);  
  }
  // Greedy Interval Covering Problem  
  int cnt = 0; 
  for (int y = 0; y < M; ++y) if (C[y] == 0) ++cnt; 
  if (cnt) printf("0\n%d\n", cnt); 
  else {
    for (int y = 0; y < M; ++y) City[y] = y; 
    sort(City, City+M, cmp); 
    cnt = 0; 
    int pos = 0, rpos = 0; 
    while (pos != M-1) {
      cnt++; 
      find_pos(pos, rpos); 
    }
    printf("1\n%d\n", cnt);
  }
  return 0;
}

Posted by riceje7 on Sat, 20 Jul 2019 18:47:54 -0700