[题目链接]
[算法]
显然 , 每个第一行的成市控制的一定是一段区间
那么 , 问题就转化为了经典的区间覆盖问题 , 贪心即可 , 时间复杂度 : 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 "); printf("%d ",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 %d ",ans); return 0; }