飞扬的小鸟 noip2014

来源:互联网 发布:网络编程技术 编辑:程序博客网 时间:2024/05/01 20:02

思路: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[n];i<=yy[n];i++)        MAX=min(MAX,f[pjy][i]);    printf("1\n%d",MAX);    return 0;}
0 1