https://www.luogu.org/problemnew/show/P1941
Bfs or Dp
#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
*/
#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;
}
}
#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;
}
来源:oschina
链接:https://my.oschina.net/u/4330019/blog/4004612