zoukankan      html  css  js  c++  java
  • 洛谷1514 引水入城

    原题链接

    对于第一个问题,显然(DFS)(BFS)一遍看看最后一排是不是全部被搜到即可。
    对于第二个问题,考虑贪心,求出第一排每个格子最大能够覆盖多少最后一排的格子,即求左端右端(显然覆盖的格子都是连续的,若不为连续,则那个断开的格子定无法到达)。
    可以使用(DP)来求出,设(L[x][y],R[x][y])分别表示对于格子((x,y)),从它出发能够覆盖最后一排的格子的最左端和最右端,显然(L[x][y] = min { L[x ^ prime][y ^ prime] },R[x][y] = max { R[x ^ prime][y ^ prime] })((x ^ prime, y ^ prime))是格子((x, y))能够到达的格子。
    这里我是使用记忆化搜索来求的,这样可以在用(DFS)求解第一个问题的时候同时求出。
    因为据说这题若构造特殊数据能把(DFS)弄爆栈,所以我使用了手工栈,另外附上非手工栈版本。

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N = 510;
    struct dd{
    	int i, x, y, xx, yy;
    };
    dd sta[N * N];
    int a[N][N], L[N][N], R[N][N], mo_x[4] = {0, 0, 1, -1}, mo_y[4] = {1, -1, 0, 0}, n, m, tp;
    bool v[N][N];
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline int minn(int x, int y)
    {
    	return x < y ? x : y;
    }
    inline int maxn(int x, int y)
    {
    	return x > y ? x : y;
    }
    /*非手工栈版本
    void dfs(int x, int y)
    {
    	v[x][y] = 1;
    	int i, xx, yy;
    	for (i = 0; i < 4; i++)
    	{
    		xx = x + mo_x[i];
    		yy = y + mo_y[i];
    		if (a[xx][yy] < a[x][y] && xx > 0 && xx <= n && yy > 0 && yy <= m)
    		{
    			if (!v[xx][yy])
    				dfs(xx, yy);
    			L[x][y] = minn(L[x][y], L[xx][yy]);
    			R[x][y] = maxn(R[x][y], R[xx][yy]);
    		}
    	}
    }
    */
    void dfs(int xo, int yo)
    {
    	sta[tp = 1].x = xo;
    	sta[1].y = yo;
    start:
    	v[sta[tp].x][sta[tp].y] = 1;
    	for (sta[tp].i = 0; sta[tp].i < 4; sta[tp].i++)
    	{
    		sta[tp].xx = sta[tp].x + mo_x[sta[tp].i];
    		sta[tp].yy = sta[tp].y + mo_y[sta[tp].i];
    		if (a[sta[tp].xx][sta[tp].yy] < a[sta[tp].x][sta[tp].y] && sta[tp].xx > 0 && sta[tp].xx <= n && sta[tp].yy > 0 && sta[tp].yy <= m)
    		{
    			if (!v[sta[tp].xx][sta[tp].yy])
    			{
    				sta[tp + 1].x = sta[tp].xx;
    				sta[tp + 1].y = sta[tp].yy;
    				tp++;
    				goto start;
    			}
    		end:
    			L[sta[tp].x][sta[tp].y] = minn(L[sta[tp].x][sta[tp].y], L[sta[tp].xx][sta[tp].yy]);
    			R[sta[tp].x][sta[tp].y] = maxn(R[sta[tp].x][sta[tp].y], R[sta[tp].xx][sta[tp].yy]);
    		}
    	}
    	if (--tp)
    		goto end;
    }
    int main()
    {
    	int i, j, s = 0, l = 1, r;
    	bool p = 0;
    	n = re();
    	m = re();
    	memset(L, 60, sizeof(L));
    	for (i = 1; i <= m; i++)
    		L[n][i] = R[n][i] = i;
    	for (i = 1; i <= n; i++)
    		for (j = 1; j <= m; j++)
    			a[i][j] = re();
    	for (i = 1; i <= m; i++)
    		if (!v[1][i])
    			dfs(1, i);
    	for (i = 1; i <= m; i++)
    		if (!v[n][i])
    		{
    			p = 1;
    			s++;
    		}
    	if (p)
    	{
    		printf("0
    %d", s);
    		return 0;
    	}
    	for (s = r = 0; l <= m; r = 0, s++)
    	{
    		for (i = 1; i <= m; i++)
    			if (L[1][i] <= l)
    				r = maxn(r, R[1][i]);
    		l = r + 1;
    	}
    	printf("1
    %d", s);
    	return 0;
    }
    
  • 相关阅读:
    字符串分割并按大小排序
    为人之气
    RMQ
    线段树
    算法中的数学
    动态规划(DP)
    图的表示
    广度优先搜索(BFS)
    深度优先搜索(DFS)
    MyBatis(3.2.3)
  • 原文地址:https://www.cnblogs.com/Iowa-Battleship/p/9812754.html
Copyright © 2011-2022 走看看