[关闭]
@ysner 2018-11-07T10:04:06.000000Z 字数 1508 阅读 2666

noip2010引水入城

贪心 DFS


这道题fst了

题面

戳我

解析

我一开始的想法是,按照高度给第一行排序,然后贪心地选取目前到不了的,高度最高的第一行的点来,一旦满足题目要求就退出。
但是这样有问题,只有
因为高度越高,不一定代表能走的越远。

有一个在考场上不一定能想到的结论:当可以满足所有位置的时候,在每个位置建立蓄水场,那么它影响的范围一定是一段连续区间
这个证还是很好证:如果中间被隔开了,那么中间那个点就不可能被影响了,因为它所在的不被影响的块被可以被影响的部分完全包围,这都影响不到就没办法了。

然后问题转化为覆盖整段区间所需要的线段数。
在判定可行后,把所有区间按左端点排序,贪心地选取即可。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cmath>
  5. #include<cstring>
  6. #include<algorithm>
  7. #include<queue>
  8. #define ll long long
  9. #define re register
  10. #define il inline
  11. #define fp(i,a,b) for(re int i=a;i<=b;++i)
  12. #define fq(i,a,b) for(re int i=a;i>=b;--i)
  13. using namespace std;
  14. const int N=600;
  15. int n,m,w[N][N],ans,mx[4]={1,-1,0,0},my[4]={0,0,1,-1},tot;
  16. bool vis[N][N],ok[N];
  17. struct dat{int l,r;il bool operator < (const dat &o) const {return l<o.l;}}a[N];
  18. il ll gi()
  19. {
  20. re ll x=0,t=1;
  21. re char ch=getchar();
  22. while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
  23. if(ch=='-') t=-1,ch=getchar();
  24. while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  25. return x*t;
  26. }
  27. il void DFS(re int x,re int y)
  28. {
  29. vis[x][y]=1;
  30. fp(i,0,3)
  31. {
  32. re int xx=x+mx[i],yy=y+my[i];
  33. if(xx<1||xx>n||yy<1||yy>m||vis[xx][yy]||w[xx][yy]>=w[x][y]) continue;
  34. DFS(xx,yy);
  35. }
  36. }
  37. int main()
  38. {
  39. n=gi();m=gi();
  40. fp(i,1,n)
  41. fp(j,1,m) w[i][j]=gi();
  42. fp(i,1,m)
  43. {
  44. DFS(1,i);
  45. fp(j,1,m)
  46. {
  47. if(!vis[n][j-1]&&vis[n][j]) a[i].l=j;
  48. if(vis[n][j]&&!vis[n][j+1]) a[i].r=j;
  49. ok[j]|=vis[n][j];
  50. }
  51. memset(vis,0,sizeof(vis));
  52. }
  53. fp(i,1,m) if(!ok[i]) ++tot;
  54. if(tot) return printf("0\n%d\n",tot),0;
  55. sort(a+1,a+1+m);
  56. re int mxr=0,i=1;
  57. while(!a[i].l&&i<=m) ++i;
  58. for(re int j=i;i<=m&&mxr<m;i=j)
  59. {
  60. re int now=mxr;
  61. while(a[j].l<=mxr+1&&j<=m) now=max(now,a[j++].r);
  62. ++ans;mxr=now;
  63. }
  64. printf("1\n%d\n",ans);
  65. return 0;
  66. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注