题意:
题解:
我们可以发现,从每一个点出发都是一棵树,也就是对于任意一个点,它的决策是一定的,状态不会改变。那么很明显是记忆化搜索
然后有一个很明显的性质,如果某个点开始,到达的区间不是连续的,那么中间这部分一定是高出旁边的,所以无论怎么走都不行。
那么dp[i][j]表示第i行j列开始能走的最大区间左右端点。
将所有都求出来之后,找最小的线段数量用树状数组即可
#include<bits/stdc++.h>
using namespace std;
#define pa pair<int,int>
const int N=505;
int mp[N][N],vis[N];
int cnt;
int xmov[]={1,0,-1,0};
int ymov[]={0,1,0,-1};
int n,m;
int can[N];
pa dp[N][N];
pa dfs(int x,int y){
if(dp[x][y]!=(pa){-1,-1})
return dp[x][y];
int f=0;
pa ans={0,0};
vector<pa>vec;
for(int i=0;i<4;i++){
int nx=xmov[i]+x,ny=y+ymov[i];
if(nx<1||nx>n||ny<1||ny>m||mp[nx][ny]>=mp[x][y])continue;
f=1;
pa v=dfs(nx,ny);
if(v==(pa){0,0})continue;
vec.push_back(v);
}
if(x==n)
vec.push_back({y,y}),can[y]=1;
f=0;
if(!vec.empty()){
sort(vec.begin(),vec.end());
ans=*vec.begin();
for(int i=1;i<vec.size();i++){
if(ans.second<vec[i].first-1){
ans={0,0};
break;
}
ans.second=max(ans.second,vec[i].second);
}
}
dp[x][y]=ans;
return ans;
}
int l[N],r[N],num[N],mx[N];
int lowbit(int x){return x&(-x);}
void add(int x,int v){
for(int i=x;i<N;i+=lowbit(i))
mx[i]=max(mx[i],v);
}
int query(int x){
int ans=0;
for(int i=x;i;i-=lowbit(i))
ans=max(ans,mx[i]);
return ans;
}
int main()
{
memset(dp,-1,sizeof(dp));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&mp[i][j]);
for(int i=1;i<=m;i++){
pa v=dfs(1,i);
if(v==(pa){0,0})continue;
add(v.first,v.second);
}
int sum=0;
for(int i=1;i<=m;i++)
if(!can[i])
sum++;
if(sum)return 0*printf("0\n%d\n",sum);
int ans=0;
int p=0;
while(p<m){
p=query(p+1);
ans++;
//if(ans>500)return 0*printf("0\n");
}
printf("1\n%d\n",ans);
return 0;
}