NOIP的题目都难以写精简题意
考虑最上面一排的某一个点对最下面一排的影响是什么样的,不难发现必须要是一段连续区间才能够符合题意。
如果不是一段连续区间,意味着中间某一段没有被覆盖的部分比周围都要高(因为当前这一个点的流域越过了这一段区间却又包含了其左右的一段区间,所以它的流域一定会包住这一个没有被流到的部分),这表示有一段区间是无论水源在哪里都无法流到的,所以就是无解了。
我们知道影响范围是一段区间之后,通过BFS把所有区间求出来,就是一个经典的线段覆盖问题了。贪心解决即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 int m[501][501] , x , y , dir[4][2] = {0,1,0,-1,1,0,-1,0}; 4 bool allVis[501] , vis[501][501]; 5 struct qj{ 6 int l , r; 7 }ans[501]; 8 bool cmp(qj a , qj b){return a.l < b.l;} 9 inline int min(int a , int b){return a < b ? a : b;} 10 inline int max(int a , int b){return a > b ? a : b;} 11 int main(){ 12 scanf("%d%d" , &x , &y); 13 for(int i = 1 ; i <= x ; i++) 14 for(int j = 1 ; j <= y ; j++) 15 scanf("%d" , &m[i][j]); 16 for(int i = 1 ; i <= y ; i++){ 17 memset(vis , 0 , sizeof(vis)); 18 ans[i].l = 501; ans[i].r = -1; 19 if((i == 1 || m[1][i] >= m[1][i - 1]) && (i == y || m[1][i] >= m[1][i + 1])){ 20 queue < pair < int , int > > q; 21 q.push(make_pair(1 , i)); 22 while(!q.empty()){ 23 pair < int , int > t = q.front(); 24 q.pop(); 25 if(t.first == x){ 26 ans[i].l = min(ans[i].l , t.second); 27 ans[i].r = max(ans[i].r , t.second); 28 allVis[t.second] = 1; 29 } 30 for(int j = 0 ; j < 4 ; j++) 31 if(t.first + dir[j][0] > 0 && t.first + dir[j][0] <= x) 32 if(t.second + dir[j][1] > 0 && t.second + dir[j][1] <= y) 33 if(!vis[t.first + dir[j][0]][t.second + dir[j][1]]) 34 if(m[t.first + dir[j][0]][t.second + dir[j][1]] < m[t.first][t.second]){ 35 vis[t.first + dir[j][0]][t.second + dir[j][1]] = 1; 36 q.push(make_pair(t.first + dir[j][0] , t.second + dir[j][1])); 37 } 38 } 39 } 40 } 41 for(int i = 1 ; i <= y ; i++) 42 if(!allVis[i]){ 43 int cnt = 1; 44 for(int j = i + 1 ; j <= y ; j++) 45 cnt += !allVis[j]; 46 cout << 0 << endl << cnt; 47 return 0; 48 } 49 sort(ans + 1 , ans + y + 1 , cmp); 50 int r = 1 , num = 0 , dir = 1; 51 while(r <= y){ 52 num++; 53 int newR = 0; 54 while(dir <= y && ans[dir].l <= r) newR = max(newR , ans[dir++].r + 1); 55 r = newR; 56 } 57 cout << 1 << endl << num; 58 return 0; 59 }