引水入城

Posted zhinv

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了引水入城相关的知识,希望对你有一定的参考价值。

引水入城

  • BFS + 贪心 贪心还能用递归写!
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>

using namespace std;
typedef pair<int,int> pii;
const int MAXN=500+1,MAXM=500+1;
int h[MAXN][MAXM], vis[MAXN][MAXM], cover[MAXM],in[MAXM];
struct Seq
{
    int l,r;
    Seq(){l=r=0;}
    bool operator < (const Seq& s)const{return l<s.l;}
} s[MAXM];
queue<pii>q;
void bfs(int Y,int n,int m,int& cnt)
{
    const int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1};
    memset(vis, 0, sizeof(vis));
    int L = 1000, R = -1;
    q.push(pii {1, Y});
    vis[1][Y]=1;
    while(!q.empty())
    {
        pii u = q.front();
        q.pop();
        int x = u.first, y = u.second;
        if(x==n){L=min(y,L);R=max(y,R);cover[y]=1;}
        for(int i=0,a,b; i<4; i++)
        {
            a=x+dx[i];b=y+dy[i];
            if(a>=1 && a<=n && b>=1 && b<=m && h[a][b]<h[x][y] && !vis[a][b])
            {
                q.push(pii {a, b});
                vis[a][b]=1;
            }
        }
    }
    if (L >= 1 && L <= m && R >= 1 && R <= m && L<=R)
    {
        s[++cnt].l = L;
        s[cnt].r = R;
    }
}
int dfs(int i,int n, int L, int R,bool& is)
{
    if (s[i].l>L)
    {
        is = false;
        return 0;
    }
    if (s[i].r >= R) return 1;
    int x = i + 1, r = s[x].r;
    for (int j = i + 2; j <= n && s[j].l <= s[i].r+1; j++)
        if (s[j].r > r) r = s[x = j].r;
    return 1 + dfs(x, n, s[x].r + 1, R, is);
}
int main()
{
    memset(h,-1,sizeof(h));
    memset(cover,0,sizeof(cover));

    int n,m;
    scanf("%d %d",&n,&m);
    for(int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            scanf("%d", &h[i][j]);

    int cnt = 0;
    for (int i = 1; i <= m; i++)
        if(h[1][i]>=h[1][i-1] && h[1][i]>=h[1][i+1])
            bfs(i, n, m, cnt);
    if (!cnt)
    {
        cout << 0 << endl << m;
        return 0;
    }
    int num = 0;
    for(int i = 1;i <= m; i++)
        if(!cover[i])num++;
    if(num)
    {
        cout<< 0 << endl << num;       
        return 0;
    }
    sort(s + 1, s+cnt + 1);
    bool is = true;
    int start = 0, r = -1, ans = 0;
    for (int i = 1; s[i].l == 1 && i <= m; i++)
        if (s[i].r > r) r = s[start = i].r;
    ans = dfs(start, cnt, 1, m, is);
    cout<< 1 << endl << ans;
    return 0;
}

(Question:)
为什么这么写不对呢?

void bfs(int Y,int n,int m,int& cnt)
{
    const int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1};
    memset(vis, 0, sizeof(vis));
    int L = 1000, R = -1;
    q.push(pii {1, Y});
    vis[1][Y] = 1;
    while(!q.empty())
    {
        pii u = q.front();
        q.pop();
        int x = u.first, y = u.second;
        if(x==n)
        {
            if (y < L) L = y;
            if (y > R) R = y;
        }
        if(x==1)in[y]=true;
        for(int i=0; i<4; i++)
        {
            int a=x+dx[i],b=y+dy[i];
            if(a>=1 && a<=n && b>=1 && b<=m)
            {
                if(h[a][b]<h[x][y]&&!vis[a][b])
                {
                    q.push(pii {a, b});
                    vis[a][b] = 1;
                }
            }
        }
    }
    if (L >= 1 && L <= m && R >= 1 && R <= m && L <= R)
    {
        s[++cnt].l = L;
        s[cnt].r = R;
    }
}

然后主函数里这样:

   for(int i=1; i<=cnt; i++)
    {
        for(int j=s[i].l;j<=s[i].r;j++)
            cover[j]=1;
    }
    int num = 0;
    for(int i = 1;i <= m; i++)
        if(!cover[i])num++;
    if(num)
    {
        cout<< 0 << endl << num;
        return 0;
    }

(???)留着以后解决吧


以上是关于引水入城的主要内容,如果未能解决你的问题,请参考以下文章

NOIP2010 引水入城

luoguP1514 引水入城 题解(NOIP2010)

P1514 引水入城

P1514 引水入城

CCF(引水入城:60分):最大流+ISAP算法

CODEVS 1066/洛谷 P1514引水入城