【题解】这题大体思路就是搜索,方法应该很多。
我的做法是,先从第一行的每一个点出发进行深搜,这样即可判断第n行的点是否能被覆盖。如果不能就输出。
深搜时,还应处理对于第一行每个点在第n行能覆盖的范围,对范围进行排序后贪心地来取即可。
//详见程序
#include <cstdio>
#include <iostream>
#include <algorithm>
const int fx[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
int n,m,ans,anss,k[505],l[505][505],r[505][505],a[505][505];
bool bo[505][505];
void dfs(int x,int y)
{
bo[x][y]=true;
for (int i=0;i<4;++i)
{
int p=x+fx[i][0],q=y+fx[i][1];
if (!p || !q || p>n || q>m) continue;
if (a[p][q]>=a[x][y]) continue;
if (!bo[p][q]) dfs(p,q);
l[x][y]=std::min(l[x][y],l[p][q]);
r[x][y]=std::max(r[x][y],r[p][q]);
}
}
bool comp(int x,int y)
{
return l[1][x]<l[1][y] || l[1][x]==l[1][y] && r[1][x]>r[1][y];
}
int main()
{
scanf("%d%d\n",&n,&m);
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j) scanf("%d",&a[i][j]);
for (int i=1;i<n;++i)
for (int j=1;j<=m;++j) l[i][j]=m+1,r[i][j]=0;
for (int i=1;i<=m;++i) l[n][i]=r[n][i]=i;
for (int i=1;i<=m;++i) dfs(1,i);
int tot=0;
for (int i=1;i<=m;++i) tot+=(!bo[n][i]);
if (tot) printf("0\n%d\n",tot);
else
{
for (int i=1;i<=m;++i) k[i]=i;
std::sort(k+1,k+m+1,comp);
int last=1;ans=0;
for (int i=1;i<=m && last<=m;)
{
int mx=0;++ans;
for (;i<=m && last>=l[1][k[i]];++i)
mx=std::max(mx,r[1][k[i]]);
if (last<=mx) last=mx+1;
}
printf("1\n%d\n",ans);
}
return 0;
}