- 引水入城
- 2016-10-28 21:18:27 @
我的思路很暴力。。就是暴力,按从大到小枚举最后一行的m个,对于每一个点,从这个点搜比它大的,搜出来在第一行的数最大是多少,然后蓄水池答案加一,然后从建蓄水池这个点搜比它矮的,所有搜到的点的can(意思是是否能够收到水)都付成true..。。
在第一次搜的过程中可以记忆化,每次每个点只搜一次就好了,并且如果搜到点的can是true,说明可以从这个点引水,不用新建了,然后退出就行,如果全搜完都没有在第一行的,那么搜不到水的点+1.。。。。。思路有问题吗。。。
附代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct BIG{
int num;
int high;
};
BIG a[1000];
bool cmp(BIG a,BIG b){
return a.high>b.high;
}
int map[1000][1000],cannotrecieve,needwater;
bool yes,vis[1000][1000],can[1000][1000];
int maxhigh,maxx,maxy,n,m;
void dfs(int x,int y){
if(yes)
return;
vis[x][y]=true;
if(x==1){
if(map[x][y]>maxhigh){
maxhigh=map[x][y];
maxx=x;
maxy=y;
}
}
if(can[x][y])
yes=true;
if(!vis[x+1][y]&&map[x+1][y]>map[x][y])
dfs(x+1,y);
if(!vis[x][y+1]&&map[x][y+1]>map[x][y])
dfs(x,y+1);
if(!vis[x-1][y]&&map[x-1][y]>map[x][y])
dfs(x-1,y);
if(!vis[x][y-1]&&map[x][y-1]>map[x][y])
dfs(x,y-1);
}
void nidfs(int x,int y){
if(can[x][y])
return;
can[x][y]=true;
if(!can[x+1][y]&&map[x+1][y]<map[x][y])
nidfs(x+1,y);
if(!can[x][y+1]&&map[x][y+1]<map[x][y])
nidfs(x,y+1);
if(!can[x-1][y]&&map[x-1][y]<map[x][y])
nidfs(x-1,y);
if(!can[x][y-1]&&map[x][y-1]<map[x][y])
nidfs(x,y-1);
}
int main(){
freopen("random.in","r",stdin);
freopen("my.out","w",stdout);
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=1;i<=m;i++)
a[i].high=map[n][i],a[i].num=i;
sort(a+1,a+m+1,cmp);
for(int i=1;i<=m;i++)
if(!can[n][a[i].num]){
memset(vis,false,sizeof(vis));
maxx=0;
maxy=0;
maxhigh=0;
yes=false;
dfs(n,a[i].num);
if(!yes){
if(maxx==0){
cannotrecieve++;
}
if(maxx!=0){
needwater++;
nidfs(maxx,maxy);
}
}
}
if(cannotrecieve==0)
printf("1\n%d",needwater);
else
printf("0\n%d",cannotrecieve);
return 0;
}