P1941 [NOIP 2014 提高组] 飞扬的小鸟 C++题解
分析
我们可以用
-
从
dp_{i,j-x_i} 转移到dp_{i,j} ; -
从
dp_{i-1,j-x_i} 转移到dp_{i,j} ; -
从
dp_{i,j+y_i} 转移到dp_{i,j} ; -
从
dp_{i-1,j+y_i} 转移到dp_{i,j} 。
那么我们可以发现内存为 i&1
)。
对于管道的坐标,我们可以用类型为 pair<int,int>
的
判断无解可以按以下步骤进行:
我们用
当
最后,遍历所有的
代码
请勿抄袭。
本题坑点:
-
数组第二维要开到
2 \times 10^3 ,不然第13 个测试点会 RE 或者 WA。 -
数组初始值一定要设大一点,如果设
10^{12} 就会在第2 个测试点 WA。
Code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int,int> PII;
const int MAXN=2e4+10,MAXM=2e3+10;
int x[MAXN],y[MAXN],dp[2][MAXM];
PII p[MAXN];
signed main(){
int n,m,k;
scanf("%lld %lld %lld",&n,&m,&k);
for(int i=1;i<=n;i++){
scanf("%lld %lld",&x[i],&y[i]);
}
for(int i=1;i<=k;i++){
int a,b,c;
scanf("%lld %lld %lld",&a,&b,&c);
p[a]={b,c};
}
int cnt=0;
for(int i=1;i<=n;i++){
for(int j=0;j<=m;j++) dp[i&1][j]=1e18;
for(int j=x[i]+1;j<=x[i]+m;j++) dp[i&1][j]=min(dp[!(i&1)][j-x[i]],dp[i&1][j-x[i]])+1;
for(int j=m+1;j<=x[i]+m;j++) dp[i&1][m]=min(dp[i&1][m],dp[i&1][j]);
for(int j=1;j<=m-y[i];j++){
dp[i&1][j]=min(dp[i&1][j],dp[!(i&1)][j+y[i]]);
}
if (p[i]!=(PII){0,0}){
bool flag=false;
for(int j=0;j<=m;j++){
if (j<=p[i].first||j>=p[i].second) dp[i&1][j]=1e18;
else if (dp[i&1][j]!=1e18) flag=true;
}
if (!flag) return puts("0"),printf("%lld\n",cnt)&0;
cnt++;
}
}
puts("1");
int ans=1e18;
for(int i=0;i<=m;i++) ans=min(ans,dp[n&1][i]);
printf("%lld\n",ans);
return 0;
}
代码时间复杂度为
The End.