。。。我觉得这道题放在贪心里应该不为过
原文:https://blog.csdn.net/qq_41513352/article/details/80726030
题目测评请点击——》https://www.acwing.com/problem/content/499/
。。。图片自行放大。。。
题解:最开始的思路是全排列+搜索,预估30分。正解是搜索+DP,先对每个
靠近河岸的点搜一次,保存下来这个点能够覆盖的区间,也就是能到达
的靠近沙漠的点,然后对于这些区间进行DP,找出覆盖所有区间用的
最少的点。另外用一个数组保存所有蓄水站能够覆盖到的点,来找到不能覆盖完的情况。
搜索部分是常规的DFS,DP部分定义d(i),表示覆盖到i点的一个状态,遍历j来寻找最优的重叠情况。
代码:
#include<bits/stdc++.h> #define MAXA 700 using namespace std; bool vis[MAXA][MAXA]; int n,m,cnt,OK[MAXA],Map[MAXA][MAXA],d[MAXA],Left[MAXA],Right[MAXA]; int drct[5][3]={{1,0},{-1,0},{0,1},{0,-1}}; void DFS(int x,int y,int origin) { if(x==n) { OK[y]=1; Left[origin]=min(Left[origin],y); Right[origin]=max(Right[origin],y); } for(int i=0;i<=3;i++) { int tx=x+drct[i][0]; int ty=y+drct[i][1]; if(!vis[tx][ty]&&Map[tx][ty]<Map[x][y]&&tx>=1&&tx<=n&&ty>=1&&ty<=m){ vis[tx][ty]=1; DFS(tx,ty,origin); } } } int main() { scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&Map[i][j]); for(int i=0;i<=MAXA;i++) Left[i]=d[i]=0x3f3f3f3f; for(int i=1;i<=m;i++) { if(Map[1][i-1]<=Map[1][i]&&Map[1][i]>=Map[1][i+1]) DFS(1,i,i); memset(vis,0,sizeof(vis)); } for(int i=1;i<=m;i++) if(!OK[i]) cnt++; if(cnt) { printf("0 "); printf("%d",cnt); return 0; } d[0]=0; for(int i=1;i<=m;i++) for(int j=1;j<=m;j++) { if(Left[j]<=i&&i<=Right[j]) d[i]=min(d[i],d[Left[j]-1]+1); } printf("1 "); printf("%d",d[m]); }