题目链接:点击打开链接
题目大意:略。
解题思路:通过第一行对应的最后一行的各个区间范围(dfs)来进行(dp)操作。
AC 代码
#include<bits/stdc++.h> #include<cmath> #define mem(a,b) memset(a,b,sizeof a); #define INF 0x3f3f3f3f using namespace std; typedef long long ll; const int maxn=510; const int dir[4][2]={-1,0,1,0,0,-1,0,1}; struct node{ int l,r; }seg[maxn][maxn]; int n,m,fail; int g[maxn][maxn], vis[maxn][maxn], dp[maxn]; void init() { fail=0; mem(vis,0); mem(dp,0); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(i!=n) seg[i][j].l=maxn,seg[i][j].r=0; else seg[i][j].l=seg[i][j].r=j; } void dfs(int x,int y) { if(vis[x][y]) return; vis[x][y]=1; for(int i=0;i<4;i++) { int dx=x+dir[i][0], dy=y+dir[i][1]; if(dx<1||dy<1||dx>n||dy>m||g[dx][dy]>=g[x][y]) continue; dfs(dx,dy); seg[x][y].l=min(seg[x][y].l,seg[dx][dy].l); seg[x][y].r=max(seg[x][y].r,seg[dx][dy].r); } } int main() { while(~scanf("%d%d",&n,&m)) { init(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&g[i][j]); for(int j=1;j<=m;j++) dfs(1,j); for(int j=1;j<=m;j++) fail+=!vis[n][j]; if(fail){ printf("0\n%d\n",fail); continue; } for(int j=1;j<=m;j++) { for(int k=seg[1][j].l; k<=seg[1][j].r; k++) { // dp[k]>dp[seg[1][j].l-1] 此题这条件不加也对,看样例,因为如果第1行6这个水站可以假设可以通过8下面对应的, // 那么必须要加这条加以更新,但是此题的特殊性导致6水站受限制于前一个水站的 l(字母) if(!dp[k] || dp[k]>dp[seg[1][j].l-1]) dp[k]=1+dp[seg[1][j].l-1]; } } printf("1\n%d\n",dp[m]); } return 0; }