zoukankan      html  css  js  c++  java
  • codevs 1066 引水入城

    我的妈呀这题卡了我两天。

    其实很简单的,就每个起点向下bfs,控制的连续的一段干旱区。然后就转换成了用最少的线段覆盖完所有区域的dp问题。

    然而?!!我一开始不知道怎么写了个神奇的贪心。。。悲惨的世界。

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=505;
    struct seg
    {
    int left,right;
    }s[maxn*3];
    int map[maxn][maxn],n,m;
    int dx[]={0,0,1,0,-1},dy[]={0,-1,0,1,0},cnt=0,dp[maxn];
    bool vis[maxn][maxn],k[maxn];
    queue <int> q;
    bool cmp(seg x,seg y)
    {
    if (x.left==y.left)
    return x.right>y.right;
    return x.left<y.left;
    }
    bool judge(int x,int y)
    {
    if ((x>=1) && (x<=n) && (y>=1) && (y<=m) && (vis[x][y]==false))
    return true;
    return false;
    }
    void bfs(int x)
    {
    memset(vis,false,sizeof(vis));
    while (!q.empty())
    q.pop();
    int minn=99999999,maxn=0;
    if (n==1)
    {
    minn=min(minn,x);
    maxn=max(maxn,x);
    k[x]=true;
    }
    vis[1][x]=true;
    q.push(x);
    while (!q.empty())
    {
    int head=q.front();
    q.pop();
    int nx,ny,tx,ty;
    if (head%m==0) nx=head/m;
    else nx=head/m+1;
    if (head-nx*m==0) ny=m;
    else ny=head-(nx-1)*m;
    for (int i=1;i<=4;i++)
    {
    int tx=nx+dx[i],ty=ny+dy[i];
    if ((judge(tx,ty)==true) && (map[nx][ny]>map[tx][ty]))
    {
    q.push((tx-1)*m+ty);
    vis[tx][ty]=true;
    if (tx==n)
    {
    minn=min(minn,ty);
    maxn=max(maxn,ty);
    k[ty]=true;
    }
    }
    }
    }
    cnt++;
    s[cnt].left=minn;
    s[cnt].right=maxn;
    }
    int main()
    {
    memset(k,false,sizeof(k));
    memset(dp,0x3f,sizeof(dp));
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
    for (int j=1;j<=m;j++)
    scanf("%d",&map[i][j]);
    for (int i=1;i<=m;i++)
    if ((map[1][i]>=map[1][i-1]) && (map[1][i]>=map[1][i+1]))
    bfs(i);
    int num=0;
    for (int i=1;i<=m;i++)
    if (k[i]==false)
    num++;
    if (num>0)
    {
    printf("0 %d ",num);
    return 0;
    }
    sort(s+1,s+cnt+1,cmp);
    dp[0]=0;
    for (int i=1;i<=m;i++)
    for (int j=1;j<=cnt;j++)
    if ((s[j].left<=i) && (s[j].right>=i))
    dp[i]=min(dp[i],dp[s[j].left-1]+1);
    printf("1 %d ",dp[m]);
    return 0;
    }

  • 相关阅读:
    2019年8月20日 item系列
    变量和字符
    python命名规则
    五大常用算法之贪心算法
    过河卒
    组成三位数
    编码问题
    FatMouse' Trade
    A Boring Game
    螺旋矩阵
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/5184782.html
Copyright © 2011-2022 走看看