zoukankan      html  css  js  c++  java
  • 【noip2010】引水入城

    题解:

    先一遍dfs看是否合法

    若合法 则从上面任意一点到达下面的点一定是连续的 拓扑求出上面每点到下面的点的区间

    把所有区间按头排序 贪心解决最少几个区间能覆盖全部区域之

    代码:

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <queue>
     4 using namespace std;
     5 const int N=501;
     6 struct info{
     7     int x,y;
     8     info(const int a=0,const int b=0):
     9         x(a),y(b){}
    10 }map[N][N],qj[N],move[4]={info(1,0),info(-1,0),info(0,1),info(0,-1)};
    11 queue <info> que;
    12 int n,m,h[N][N],bo[N][N],bein[N][N],ans;
    13 bool check(info x,info y){ return x.x+y.x>0 && x.y+y.y>0 && x.x+y.x<=n && x.y+y.y<=m; }
    14 inline bool cmp(info a,info b){ return a.x<b.x; }
    15 void search(info now){
    16     que.push(now);
    17     bo[now.x][now.y]=1;
    18     while (!que.empty()){
    19         now=que.front();
    20         que.pop();
    21         for (int i=0;i<4;i++)
    22         if (check(now,move[i]))
    23         if (!bo[now.x+move[i].x][now.y+move[i].y] && h[now.x][now.y]>h[now.x+move[i].x][now.y+move[i].y]){
    24             info ne=info(now.x+move[i].x,now.y+move[i].y);
    25             bo[ne.x][ne.y]=1;
    26             que.push(ne);
    27         }
    28     }
    29 }
    30 bool checkbo(){
    31     for (int i=1;i<=m;i++)
    32     if (!bo[1][i]) search(info(1,i));
    33     for (int i=1;i<=m;i++)
    34     if (!bo[n][i]) ++ans;
    35     return ans;
    36 }
    37 void makebein(){
    38     for (int i=1;i<=n;i++)
    39     for (int j=1;j<=m;j++)
    40     for (int k=0;k<4;k++)
    41     if (check(info(i,j),move[k]))
    42     if (h[i][j]<h[i+move[k].x][j+move[k].y]) ++bein[i+move[k].x][j+move[k].y];
    43 }
    44 int max(int x,int y){
    45     if (!x) return y;
    46     if (!y) return x;
    47     return x>y ? x : y;
    48 }
    49 int min(int x,int y){
    50     if (!x) return y;
    51     if (!y) return x;
    52     return x<y ? x : y;
    53 }
    54 void makemap(){
    55     for (int j=1;j<=m;j++) map[n][j]=info(j,j);
    56     for (int i=1;i<=n;i++)
    57     for (int j=1;j<=m;j++)
    58     if (!bein[i][j]) que.push(info(i,j));
    59     while (!que.empty()){
    60         info now=que.front();
    61         que.pop();
    62         for (int i=0;i<4;i++)
    63         if (check(now,move[i]))
    64         if (h[now.x][now.y]<h[now.x+move[i].x][now.y+move[i].y]){
    65             info ne=info(now.x+move[i].x,now.y+move[i].y);
    66             map[ne.x][ne.y].x=min(map[ne.x][ne.y].x,map[now.x][now.y].x);
    67             map[ne.x][ne.y].y=max(map[ne.x][ne.y].y,map[now.x][now.y].y);
    68             if (!--bein[ne.x][ne.y]) que.push(ne);
    69         }
    70     }
    71 }
    72 void makeqj(){
    73     makemap();
    74     for (int i=1;i<=m;i++) qj[i]=map[1][i];
    75 }
    76 int getans(){
    77     sort(qj+1,qj+m+1,cmp);
    78     int res=0;
    79     for (int i=1,j=1;i<=m && j<=m;){
    80         ++res;
    81         int x=0;
    82         for (;qj[i].x<=j && i<=m;i++)
    83         if (x<qj[i].y) x=qj[i].y;
    84         j=x+1;
    85     }
    86     return res;
    87 }
    88 int main(){
    89     scanf("%d%d",&n,&m);
    90     for (int i=1;i<=n;i++)
    91     for (int j=1;j<=m;j++) scanf("%d",&h[i][j]);
    92     if (checkbo()){
    93         printf("0
    %d",ans);
    94         return 0;
    95     }
    96     makebein();
    97     makeqj();
    98     printf("1
    %d",getans());
    99 }
    View Code
  • 相关阅读:
    求树的某一层的节点最多
    快排 PAT 1101
    PAT 1098
    PAt 1099
    多项式求和
    pat 1100
    getline 函数
    数字的标准写法
    线性回归
    HTTP 中状态码 302的使用场景
  • 原文地址:https://www.cnblogs.com/g-word/p/3383412.html
Copyright © 2011-2022 走看看