[Luogu] 飞扬的小鸟
https://www.luogu.org/problemnew/show/P1941
Bfs or Dp
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; const int N = 1e4 + 10; #define gc getchar() #define oo 99999999 struct Node_1 { int X, D, U; } P[N]; struct Node_2 { int U, D; } M[N]; struct node { int x, y, step; }; int n, m, k; int Answer = oo, Maxx; queue <node> Q; inline int read() { int x = 0; char c = gc; while(c < '0' || c > '9') c = gc; while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc; return x; } int up, down; int vis[N][1000]; inline void Bfs() { for(int i = m; i >= 1; i --) { node now; now.x = 2; down = i - M[1].D, up = i + M[1].U; if(down > P[2].D && down < P[2].U && vis[2][down] == 0) { now.y = down; now.step = 0; vis[now.x][now.y] = 1; Q.push(now); } if(up > P[2].D && up < P[2].U && vis[2][up] == 0) { now.y = min(up, m); vis[now.x][now.y] = 1; now.step = 1; Q.push(now); } } while(!Q.empty()) { node topp = Q.front(); Q.pop(); Maxx = max(Maxx, topp.x); if(topp.x == n + 1) { Answer = min(Answer, topp.step); continue ; } int y = topp.y, x = topp.x; node nxt; nxt.x = x + 1; down = y - M[x].D, up = y + M[x].U; if(down > P[x + 1].D && down < P[x + 1].U) { nxt.y = down; nxt.step = topp.step; if(vis[nxt.x][nxt.y] == 0) { vis[nxt.x][nxt.y] = nxt.step; Q.push(nxt); } else { if(vis[nxt.x][nxt.y] > nxt.step) { Q.push(nxt); vis[nxt.x][nxt.y] = nxt.step; } } } nxt.y = up; nxt.step = topp.step; up = min(up, m); while(up > P[x + 1].D && up < P[x + 1].U) { nxt.y = min(nxt.y, m); if(vis[nxt.x][nxt.y] == 0) { nxt.step ++; vis[nxt.x][nxt.y] = nxt.step; Q.push(nxt); } else { if(vis[nxt.x][nxt.y] > nxt.step + 1) { nxt.step ++; Q.push(nxt); vis[nxt.x][nxt.y] = nxt.step; } } if(nxt.y == m) break; nxt.y += M[x].U; up = min(nxt.y, m); } } } int main() { n = read(); m = read(); k = read(); for(int i = 1; i <= n; i ++) M[i].U = read(), M[i].D = read(), P[i].U = m + 1; P[n + 1].U = m + 1; for(int i = 1; i <= k; i ++) { int X = read() + 1; P[i].X = X; P[X].D = read(); P[X].U = read(); } Bfs(); if(Answer != oo) cout << 1 << "\n" << Answer; else { cout << 0 << "\n"; int js(0); for(int i = 1; i <= k; i ++) if(P[i].X <= Maxx) js ++; cout << js; } return 0; } /* 5 5 0 3 3 2 1 2 3 2 1 3 2 */
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cctype> #include<algorithm> #define N 10003 #define M 1003 #define For(i,j,k) for(int i=j;i<=k;++i) int read() { int x=0,l=1; char ch=getchar(); while(!isdigit(ch)) { if (ch=='-') l=-1; ch=getchar(); } while(isdigit(ch)) x=x*10+(ch^48),ch=getchar(); return x*l; } using namespace std; int a[N][M],x[N],y[N],hi[N]; //a存到当前点的最优步数 short hk[M<<1],wal[M<<1]; //hk记列,wal记行,这只是循环队列,不要在意变量名 bool fl[N][M],mp[N][M],li[N]; //fl--某个点有没有被走过,mp--某个点有没有管子,li--记录某一列能不能到 int main() { int an,n=read(),m=read(),k=read(),mo,ha,jzm,l=0,r,ac,p=0,kk,ff; ac=m<<1; For(i,0,n-1) x[i]=read(),y[i]=read(),hi[i]=10000; //hi记录某一列上限,如果是最大值表示无上限 For(i,1,k) { jzm=read(),mo=read(),ha=read(); //不要在意变量名x2 For(j,1,mo) mp[jzm][j]=1; For(j,ha,m) mp[jzm][j]=1; hi[jzm]=ha-1; //mp,hi标记 } r=m; For(i,1,m) wal[i]=i; //第0列入队 while(l<r) { l++; mo=hk[l%ac]; ha=wal[l%ac]; ff=an=0; li[mo]=1; if (mo==n) continue; kk=min(m,hi[mo+1]); for(int i=ha+x[mo]; i<=kk; i+=x[mo]) { //枚举当前点可以到的点 an++; if (mp[mo+1][i]) continue; //判断当前有没有管道(下面的,碰上面管道就退循环了) if (!fl[mo+1][i]) { //没走过就入队 fl[mo+1][i]=1; r++; hk[r%ac]=mo+1; wal[r%ac]=i; a[mo+1][i]=a[mo][ha]+an; } else if (a[mo+1][i]>a[mo][ha]+an) a[mo+1][i]=a[mo][ha]+an; //更新值 if (fl[mo][i]&&a[mo][i]<=a[mo][ha]+an) { ff=1; break; } //重要剪枝!如果当前点顶上有点比他更优那就可以退了 //但是在这之前的循环是必要的,因为这时走的点是他顶上那个点走不到的 } if (!mp[mo+1][m]&&!ff) { //特判到顶的情况 if (!fl[mo+1][m]) { fl[mo+1][m]=1; r++; hk[r%ac]=mo+1; wal[r%ac]=m; a[mo+1][m]=a[mo][ha]+an+1; } else if (a[mo+1][m]>a[mo][ha]+an+1) a[mo+1][m]=a[mo][ha]+an+1; } if (ha-y[mo]>0) { //特判下降情况 jzm=ha-y[mo]; if (!mp[mo+1][jzm]) { if (!fl[mo+1][jzm]) { fl[mo+1][jzm]=1; r++; hk[r%ac]=mo+1; wal[r%ac]=jzm; a[mo+1][jzm]=a[mo][ha]; } else if (a[mo+1][jzm]>a[mo][ha]) a[mo+1][jzm]=a[mo][ha]; } } } for(int i=n; i>=0; i--) //输出 if (li[i]) { if (i==n) { printf("1\n"); an=2100000000; For(j,1,m) if (an>a[n][j]&&fl[n][j]) an=a[n][j]; printf("%d\n",an); return 0; } printf("0\n"); an=0; for(int j=i; j>=1; j--) if (hi[j]!=10000) an++; printf("%d\n",an); return 0; } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int MAXDP=100000; int l[10010],h[10010]; int dp[10010][1010]; int x[10010],y[10010]; bool p[10010]; int main() { int n,i,j,k,m,w; scanf("%d%d%d",&n,&m,&k); for(i=0; i<n; i++) { scanf("%d%d",&x[i],&y[i]); l[i]=0; h[i]=m+1; } l[n]=0; h[n]=m+1; for(i=0; i<k; i++) { scanf("%d",&w); scanf("%d%d",&l[w],&h[w]); p[w]=true; } for(i=1; i<=n; i++) { for(j=0; j<=m; j++) { dp[i][j]=MAXDP; } } dp[0][0]=MAXDP; for(i=1; i<=m; i++) { dp[0][i]=0; } for(i=1; i<=n; i++) { for(j=x[i-1]; j<=m; j++) { if(j==m) { for(w=m-x[i-1]; w<=m; w++) { dp[i][j]=min(dp[i][j],dp[i-1][w]+1); dp[i][j]=min(dp[i][j],dp[i][w]+1); } } dp[i][j]=min(dp[i][j],dp[i-1][j-x[i-1]]+1); dp[i][j]=min(dp[i][j],dp[i][j-x[i-1]]+1); } for(j=max(1,l[i]+1); j<=min(m-y[i-1],h[i]-1); j++) { dp[i][j]=min(dp[i][j],dp[i-1][j+y[i-1]]); } for(j=l[i]; j>=1; j--) { dp[i][j]=MAXDP; } for(j=h[i]; j<=m; j++) { dp[i][j]=MAXDP; } } int ans=MAXDP; int cnt=k; for(i=n; i>=1; i--) { for(j=l[i]+1; j<=h[i]-1; j++) { ans=min(ans,dp[i][j]); } if(ans<MAXDP) { break; } if(p[i]==true) { k--; } } if(cnt==k) { printf("1\n%d",ans); } else { printf("0\n%d",k); } return 0; }