NOIP 2010 引水入城 解题报告
可以如果题目有解的话(即,最后一排中没有没有水的城市。),那么第一排中的任意一个城市能够运水到达最后一行的城市是一个区间,是连续的!证明我不写了,我也不会,呵呵。以前看过一篇,然后知道这个信息之后,直接贪心就行了,看代码吧:
#include <stdio.h> #include <string.h> #include <stdlib.h> int num[500][500]; int can[500][500]; int m, n; #define deal(i, j) if((((i) >= 0 && (i) < n && (j) >= 0 && (j) < m)) && num[a][b] > num[i][j]){srch((i), (j));} struct area{ int start, end; }area[500]; void srch(int a, int b) { if(can[a][b]){ return; } can[a][b] = 1; deal(a - 1, b); deal(a + 1, b); deal(a, b - 1); deal(a, b + 1); } #define deal2(i, j) if(((i) >= 0 && (i) < n && (j) >= 0 && (j) < m) && num[(i)][(j)] > num[a][b]){search((i), (j), c);} void search(int a, int b, int c) { if(a == 0){ int k = 1; if(area[b].start > c){ area[b].start = c; deal2(a - 1, b); deal2(a + 1, b); deal2(a, b - 1); deal2(a, b + 1); k = 0; } if(area[b].end < c){ area[b].end = c; if(k){ deal2(a - 1, b); deal2(a + 1, b); deal2(a, b - 1); deal2(a, b + 1); } } return; } deal2(a, b - 1); deal2(a, b + 1); deal2(a - 1, b); deal2(a + 1, b); } int com(const void *a, const void *b) { struct area *i = (struct area*)a, *j = (struct area*)b; return i->start - j->start; } int main(int argc, char **argv) { int i, j, k, ans = 0; int s = -1; scanf("%d%d", &n, &m); for(i = 0; i < n; i++){ for(j = 0; j < m; j++){ scanf("%d", &num[i][j]); } } for(i = 0; i < m; i++){ srch(0, i); } for(i = 0; i < m; i++){ if(!can[n - 1][i]){ ans++; } } if(ans != 0){ printf("0\n%d\n", ans); return 0; }else{ printf("1\n"); } for(i = 0; i < m; i++){ area[i].start = 0xFFFFFFF; area[i].end = -1; } for(i = 0; i < m; i++){ search(n - 1, i, i); } qsort(area, m, sizeof(struct area), com); i = 0; while(i < m && s + 1 < m){ if(area[i].start <= s + 1){ ans++; k = 0; while(i < m && area[i].start <= s + 1){ if(area[i].end > k){ k = area[i].end; } i++; } s = k; } } printf("%d\n", ans); return 0; }