标签:nbsp 就会 col stdin 计算 tps break 现在 hit
非常感到抱歉,由于昨天有点忙,这道题的题解没写,今天补上,争取写的更加详细一点,让大家明白。
看一下题意:
在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠。该国的行政区划十分特殊,刚好构成一个NNN 行×M \times M×M 列的矩形,如上图所示,其中每个格子都代表一座城市,每座城市都有一个海拔高度。
为了使居民们都尽可能饮用到清澈的湖水,现在要在某些城市建造水利设施。水利设施有两种,分别为蓄水厂和输水站。蓄水厂的功能是利用水泵将湖泊中的水抽取到所在城市的蓄水池中。
因此,只有与湖泊毗邻的第111 行的城市可以建造蓄水厂。而输水站的功能则是通过输水管线利用高度落差,将湖水从高处向低处输送。故一座城市能建造输水站的前提,是存在比它海拔更高且拥有公共边的相邻城市,已经建有水利设施。由于第NNN 行的城市靠近沙漠,是该国的干旱区,所以要求其中的每座城市都建有水利设施。那么,这个要求能否满足呢?如果能,请计算最少建造几个蓄水厂;如果不能,求干旱区中不可能建有水利设施的城市数目。
输入格式:
每行两个数,之间用一个空格隔开。输入的第一行是两个正整数N,MN,MN,M,表示矩形的规模。接下来NNN 行,每行MMM 个正整数,依次代表每座城市的海拔高度。
输出格式:
两行。如果能满足要求,输出的第一行是整数111,第二行是一个整数,代表最少建造几个蓄水厂;如果不能满足要求,输出的第一行是整数000,第二行是一个整数,代表有几座干旱区中的城市不可能建有水利设施。
这次我把题意都拿了上来,洛谷有这道题,所以大家可以去洛谷等其他oj看题意以及测试数据,这里就不多说了,主要讲一讲思路。
从这道题的数据范围来看,n、m<=500非常的大,所以大家需要考虑高效的算法,否则一不容易就会超时,这道题说了水能够从高处向地处流,然后求出最少建造的蓄水厂,
如果没有就输出‘0’......(还是看题意吧,题意说的非常清楚)。
不难发现,我们必须要知道湖泊上的城市作为蓄水厂能够流到那里,这需要dfs进行求解,dfs也是需要技巧,需要记录当前位置能够输送到靠近沙漠的那些城市。
这样我们就得到了湖泊城市与沙漠城市之间的关系,简化了问题,我们再看一看湖泊城市对应的沙漠城市,就发现对应的沙漠城市一定是连续的(想一想,为什么?)如果不连续
那么就没有解了,就需要输出不能灌溉城市的个数了,对于连续的城市,我们不难想到贪心中的区间覆盖问题,我们需要对区间进行排序,先排序左边(左边小的靠前),
左边相同看右边(右边大的靠前),这与区间选点的顺序不同(这很重要,否则不能得到最优解),然后按照区间覆盖的方案去做就行了,大家可以去看看其他博客上面区间
覆盖的解释,不难,然后与这道题对应下,关于区间覆盖的问题,我以后会说,下面就是代码:
// P1514 // dfs + 贪心(区间覆盖问题) #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]; // 其中L[1]表第1座靠近湖泊的城市对应的最左边的沙漠城市 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); } // 贪心 区间覆盖问题 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; }
标签:nbsp 就会 col stdin 计算 tps break 现在 hit
原文地址:https://www.cnblogs.com/yifeiWa/p/11220241.html