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;
    }

  • 相关阅读:
    梯度下降算法 (转)
    机器学习
    杭电1097-A hard puzzle
    动态规划初步习题(紫书)
    4.21考试题解
    【bzoj4445 scoi2015】小凸想跑步
    【bzoj4444 scoi2015】国旗计划
    【bzoj4443 scoi2015】小凸玩矩阵
    【luogu P4007 清华集训2017】小Y和恐怖奴隶主
    【luoguP4006 清华集训2017】小Y和二叉树
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/5184782.html
Copyright © 2011-2022 走看看