【NOIP2014提高组T3】飞扬的小鸟-完全背包
(本人本题完成于2016-7-23)
题目:飞扬的小鸟-题目
做法:可以看出,这道题目类似于完全背包问题,可以用动态规划解决。用f[i][j]表示到达坐标(i,j)时最小的点击次数。注意处理顶部的情况。
以下是本人代码:
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define inf 99999999
using namespace std;
int n,m,k,passed=0,in[20010]={0},de[20010]={0}; //in[i],de[i]:在横坐标为i的位置的点击一次的上升高度和不点击的下降高度
int f[2][2010]={0}; //滚动数组
int bot[20010]={0},top[20010]={0}; //bot[i],top[i]:横坐标为i的管道缝隙的下沿高度和上沿高度
int now,past;
int main()
{
scanf("%d %d %d",&n,&m,&k);
for(int i=0;i<=n-1;i++)
scanf("%d %d",&in[i],&de[i]);
for(int i=0;i<=n;i++)
top[i]=m+1;
for(int i=1;i<=k;i++)
{
int x;
scanf("%d",&x);
scanf("%d %d",&bot[x],&top[x]);
}
now=1;past=0;
for(int i=1;i<=n;i++)
{
for(int j=0;j<=m;j++)
f[now][j]=inf;
for(int j=1;j<=m;j++)
if (j-in[i-1]>0) f[now][j]=min(f[now][j],min(f[past][j-in[i-1]]+1,f[now][j-in[i-1]]+1));
for(int j=m-in[i-1];j<=m;j++)
f[now][m]=min(f[now][m],min(f[past][j]+1,f[now][j]+1)); //处理顶部情况
for(int j=m;j>=1;j--)
if (j+de[i-1]<=m) f[now][j]=min(f[now][j],f[past][j+de[i-1]]);
for(int j=0;j<=bot[i];j++) f[now][j]=inf;
for(int j=top[i];j<=m;j++) f[now][j]=inf;
if (top[i]<=m)
for(int j=1;j<=m;j++) if (f[now][j]!=inf) {passed++;break;} //如果当前位置有管道缝隙并通过了,统计
int t=now;now=past,past=t;
}
int ans=inf;
for(int i=1;i<=m;i++) ans=min(ans,f[past][i]);
if (passed<k) printf("0\n%d",passed);
else printf("1\n%d",ans);
return 0;
}