您的位置:首页 > 其它

飞扬的小鸟 noip2014

2016-10-12 19:12 351 查看
思路:DP,完全背包,f[i][j]表示到第i列从下往上第j个最少需要的点击次数

i肯定是从i-1推过来的嘛,所以可以滚动

有两种情况,上升或下降,所以有两个方程,其中上升是完全背包,因为可以点多次嘛

特别注意,上升时,当j=m时,要特殊处理,因为上升最多到m

这个题证明了我完全背包掌握太差!!!!

#include<cstdio>
int n,m,k,x[10001],y[10001],xx[10001],yy[10001],f[2][1001];
int MAX=0xfffffff,ljj=0;
bool b[10001],bo;
int min(int a,int b){return a>b?b:a;}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for (int i=0;i<n;i++)
scanf("%d%d",&x[i],&y[i]);
for (int i=1;i<=n;i++)
xx[i]=1,yy[i]=m;

int P,L,H;
for (int i=1;i<=k;i++)
{
scanf("%d%d%d",&P,&L,&H);
xx[P]=L+1; yy[P]=H-1; b[P]=1;
}

int pjy=1,eden=0;
for (int i=1;i<=n;i++)
{
bo=0;
pjy^=1; eden^=1;
for (int j=1;j<=m;j++) f[pjy][j]=MAX;

for (int j=x[i-1]+1;j<m;j++)
f[pjy][j]=min(f[pjy][j],min(f[eden][j-x[i-1]]+1,f[pjy][j-x[i-1]]+1));

for (int j=m-x[i-1];j<=m;j++)
f[pjy][m]=min(f[pjy][m],min(f[eden][j]+1,f[pjy][j]+1));

for (int j=xx[i];j<=yy[i];j++)
{
if (j+y[i-1]<=m) f[pjy][j]=min(f[pjy][j],f[eden][j+y[i-1]]);

if (f[pjy][j]<MAX) bo=1;

}

for (int j=0;j<xx[i];j++) f[pjy][j]=MAX;

for (int j=yy[i]+1;j<=m;j++) f[pjy][j]=MAX;

if (!bo){printf("0\n%d",ljj);return 0;}

if (b[i]) ljj++;

}

for (int i=xx
;i<=yy
;i++)

MAX=min(MAX,f[pjy][i]);

printf("1\n%d",MAX);

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: