洛谷1514 引水入域 dp+记忆化搜索
题目链接:https://www.luogu.com.cn/problem/P1514
题意大致是:给定一个(n,m)的数值矩阵,可以在第一行建造水库,如果一个格子周围的某格子值小于它,那水就可以流到它周围的那个格子,问需要在第一行建造多少水库使得最后一行能够被完全覆盖,如果不能完全覆盖就求出不能覆盖的格子的数量。
主要思路就是在第一行每个点出发的水能到达第n行的区间可以获得(可以用反证法证明每个点出发的水如果能到达第n行那么它的覆盖区间一定是连续的),如果能够完全覆盖第n行则用最小区间数覆盖可以求出最少需要多少个点可以覆盖第n行,
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef unsigned int ui; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 #define pf printf 7 #define mem(a,b) memset(a,b,sizeof(a)) 8 #define prime1 1e9+7 9 #define prime2 1e9+9 10 #define scand(x) scanf("%llf",&x) 11 #define f(i,a,b) for(int i=a;i<=b;i++) 12 #define scan(a) scanf("%d",&a) 13 #define dbg(args) cout<<#args<<":"<<args<<endl; 14 #define pb(i) push_back(i) 15 #define ppb(x) pop_back(x) 16 #define inf 0x3f3f3f3f 17 #define maxn 1005 18 int n,m,t,a[maxn][maxn],l[maxn][maxn],r[maxn][maxn],vis[maxn][maxn]; 19 //l[i][j]从(i,j)位置出发的水最多能覆盖到最后一行的左端的位置, 20 //r[i][j]从(i,j)位置出发的水最多能覆盖到最后一行的最右端的位置 21 int dir[][2]={{1,0},{0,-1},{-1,0},{0,1}}; 22 void dfs(int x,int y) 23 { 24 vis[x][y]=true;//表明(x,y)位置的l,r信息都被处理过 25 int xx,yy; 26 f(i,0,3) 27 { 28 xx=x+dir[i][0]; 29 yy=y+dir[i][1]; 30 if(xx<=0||xx>n||yy<=0||yy>m)continue; 31 if(a[xx][yy]>=a[x][y])continue; 32 if(!vis[xx][yy]) 33 { 34 dfs(xx,yy); 35 } 36 l[x][y]=min(l[x][y],l[xx][yy]); 37 r[x][y]=max(r[x][y],r[xx][yy]); 38 } 39 } 40 int main() 41 { 42 //freopen("input.txt","r",stdin); 43 //freopen("output.txt","w",stdout); 44 std::ios::sync_with_stdio(false); 45 scan(n); 46 scan(m); 47 f(i,1,n) 48 f(j,1,m) 49 { 50 scan(a[i][j]); 51 } 52 mem(l,inf); 53 mem(r,-inf); 54 f(1,1,m) 55 { 56 l[n][i]=r[n][i]=i;//最下面一层,初始情况区间只覆盖自己 57 } 58 f(i,1,m) 59 { 60 if(!vis[1][i]) 61 dfs(1,i); 62 } 63 bool flag=true; 64 int cnt=0; 65 f(i,1,m) 66 { 67 if(!vis[n][i]) 68 { 69 flag=false; 70 cnt++; 71 } 72 } 73 if(!flag) 74 { 75 pf("0\n%d",cnt);//有多少个点无法覆盖 76 } 77 else 78 { 79 int num=0; 80 int left=1,maxr=0;//最小区间数覆盖 81 while(left<=m) 82 { 83 maxr=0; 84 f(i,1,m) 85 { 86 if(l[1][i]<=left)//找到覆盖left点的区间右端值的最大值 87 maxr=max(maxr,r[1][i]); 88 } 89 left=maxr+1; 90 num++; 91 } 92 pf("1\n%d\n",num); 93 /* f(i,1,m) 94 { 95 pf("%d %d\n",l[1][i],r[1][i]); 96 }*/ 97 } 98 return 0; 99 }
每一个不曾起舞的日子,都是对生命的辜负。