【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\n%d",ans);

94         return 0;

95     }

96     makebein();

97     makeqj();

98     printf("1\n%d",getans());

99 }
View Code

 

你可能感兴趣的:(IP)