[NOIP 2010] 引入入城

[题目链接]

         https://loj.ac/problem/2595

[算法]

        显然 , 每个第一行的成市控制的一定是一段区间

        那么 , 问题就转化为了经典的区间覆盖问题 , 贪心即可 , 时间复杂度 : O(N^3)

[代码]

        

#include<bits/stdc++.h>
using namespace std;
#define MAXN 510
const int dx[4] = {0,0,-1,1};
const int dy[4] = {-1,1,0,0};

int n,m,len;
int a[MAXN][MAXN];
pair<int,int> range[MAXN];
bool mark[MAXN];
bool visited[MAXN][MAXN];

template <typename T> inline void read(T &x)
{
    T f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; 
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    x *= f;
}
inline bool valid(int x,int y)
{
        return x >= 1 && x <= n && y >= 1 && y <= m;
}
inline pair<int,int> bfs(int x,int y)
{
        int l = 0 , r = 0;
        queue< pair<int,int> > q;
        memset(visited,false,sizeof(visited));
        q.push(make_pair(x,y));
        visited[x][y] = true;
        while (!q.empty())
        {
                pair<int,int> cur = q.front();
                q.pop();
                for (int i = 0; i < 4; i++)
                {
                        int x = cur.first + dx[i] , y = cur.second + dy[i];
                        if (valid(x,y) && a[x][y] < a[cur.first][cur.second] && !visited[x][y])
                        {
                                visited[x][y] = true;
                                q.push(make_pair(x,y));
                        }
                }
        }
        for (int i = 1; i <= m; i++)
        {
                if (visited[n][i])
                {
                        mark[i] = true;
                        if (!l) l = r = i;
                        else r++;
                } 
        }
        return make_pair(l,r);
}
inline bool cmp(pair<int,int> a,pair<int,int> b)
{
        if (a.first != b.first) return a.first < b.first;
        else return a.second > b.second;
}

int main() 
{
        
        read(n); read(m);
        for (int i = 1; i <= n; i++)
        {
                for (int j = 1; j <= m; j++)
                {
                        read(a[i][j]);
                }
        }
        for (int i = 1; i <= m; i++) 
        {
                pair<int,int> tmp = bfs(1,i);
                if (tmp.first) range[++len] = tmp;
        }
        int cnt = 0;
        for (int i = 1; i <= m; i++)
        {
                if (mark[i])
                        cnt++;
        }
        if (cnt < m)
        {
                printf("0\n");
                printf("%d\n",m - cnt);
                return 0;
        }
        sort(range + 1,range + len + 1,cmp);
        int r = range[1].second , ans = 1 , pos = 2;
        while (r < m)
        {
                int mx = r;
                while (pos <= len && range[pos].first <= r + 1)
                {
                        mx = max(mx,range[pos].second);
                        pos++;
                }
                r = mx;
                ans++;
        }
        printf("1\n%d\n",ans);
        
        return 0;
    
}

 

posted @ 2018-09-18 16:09  evenbao  阅读(155)  评论(0编辑  收藏  举报