题解:本题主要考查背包综合。
简要题意:一个长为
n
n
n,高为
m
m
m的二维平面,其中有
k
k
k个管道。小鸟每个单位时间向右移的距离为
1
1
1,在横坐标位置
0
∼
n
0∼n
0∼n点击屏幕,小鸟就会上升高度
X
i
X_i
Xi,每个单位时间可以点击多次。如果在横坐标位置
0
∼
n
0∼n
0∼n不点击屏幕,小鸟就会下降一定高度
Y
i
Y_i
Yi,小鸟高度等于
0
0
0或者小鸟碰到管道时失败,小鸟高度为
m
m
m时,无法再上升。
1.dp:用
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示横坐标为
i
i
i时高度为
j
j
j的最少点击次数。
上升时:由前一个单位时间内的
j
−
X
i
j-X_i
j−Xi跳了一次得来的或由现在的
j
−
X
i
j-X_i
j−Xi跳了一次得来的:
f
[
i
]
[
j
]
=
m
i
n
(
f
[
i
]
[
j
−
x
[
i
]
]
+
1
,
f
[
i
−
1
]
[
j
−
x
[
i
]
]
+
1
)
;
f[i][j]=min(f[i][j-x[i]]+1,f[i-1][j-x[i]]+1);
f[i][j]=min(f[i][j−x[i]]+1,f[i−1][j−x[i]]+1);
下降时:由前一个单位时间内
j
+
Y
i
j+Y_i
j+Yi下降而来的,所以
f
[
i
]
[
j
]
=
m
i
n
(
f
[
i
]
[
j
]
,
f
[
i
−
1
]
[
j
+
y
[
i
]
]
)
;
f[i][j]=min(f[i][j],f[i-1][j+y[i]]);
f[i][j]=min(f[i][j],f[i−1][j+y[i]]);
如果是在顶层就只要将向上跳时溢出
m
m
m高度与自己比较即可。
2.注意事项:循环高度时,应该为
j
<
=
m
+
X
i
j<=m+X_i
j<=m+Xi,判断卡在顶部的情况,因为如果只是
j
<
=
m
j<=m
j<=m就很有可能把这种情况忽略。
数组要开大一点
代码如下:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int f[11000][2666],x[20000],y[20000];
int guanl[20000],guanh[20000],vis[20000];
int n,m,k,ans=0x3f3f3f3f,sum;
int main()
{
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
cin>>x[i]>>y[i];
for(int i=1;i<=n;i++){guanl[i]=1;guanh[i]=m;}
for(int i=1;i<=k;i++)
{
int a,b,c;
cin>>a>>b>>c;
vis[a]=1;
guanl[a]=b+1;guanh[a]=c-1;
}
memset(f,0x3f3f3f3f,sizeof(f));
for(int i=1;i<=m;i++)f[0][i]=0;
for(int i=1;i<=n;i++)
{
for(int j=x[i]+1;j<=m+x[i];j++)
f[i][j]=min(f[i][j-x[i]]+1,f[i-1][j-x[i]]+1);
for(int j=m+1;j<=m+x[i];j++)
f[i][m]=min(f[i][m],f[i][j]);
for(int j=1;j<=m-y[i];j++)
f[i][j]=min(f[i][j],f[i-1][j+y[i]]);
for(int j=1;j<=guanl[i]-1;j++)
f[i][j]=0x3f3f3f3f;
for(int j=guanh[i]+1;j<=m;j++)
f[i][j]=0x3f3f3f3f;
}
for(int i=1;i<=m;i++)ans=min(ans,f[n][i]);
if(ans<0x3f3f3f3f)
{
cout<<"1"<<endl<<ans;
cin>>n;
return 0;
}
int i,j;
for(i=n;i>=1;i--)//找到没有通过的位置
{
for(j=1;j<=m;j++)
if(f[i][j]<0x3f3f3f)break;
if(j<=m)break;
}
for(j=1;j<=i;j++)
if(vis[j])sum++;
cout<<"0"<<endl<<sum;
return 0;
}