【USACO题库】3.1.6 Stamps邮票

来源:互联网 发布:openwrt 网络配置 编辑:程序博客网 时间:2024/05/17 19:22
这一道题,算是我“千辛万苦”才做出来的吧。因为,我在时超70后代写了很久,才找出了一个能对但又不超时的方法。下边,来说一说我的超时思想:用i来枚举,从1一直到2000000,在一个个判断,知道i不可以结合出来就输出并结束程序,(呵呵,不超时的话,那就是相当于中了2亿元的大奖了)好了看一看超时代吗:
#include<cstdio>using namespace std;int a[51],f[2000001];bool bz[2000001];int k,n;bool pd(int x){    int i;    f[x]=666666666;    for (i=1;i<=x/2;i++)    {        if (bz[i]==true&&bz[x-i]==true)        {            bz[x]=true;            if (f[x]>f[i]+f[x-i]) f[x]=f[i]+f[x-i];        }    }    if (f[x]>k) return false;    else return bz[x];}int main(){    int i,j;    scanf("%d%d",&k,&n);    for (i=1;i<=n;i++)    {        scanf("%d",&a[i]);        for (j=1;j<=k;j++)        {            bz[a[i]*j]=true;            f[a[i]*j]=j;        }    }    for (i=1;i<=2000000;i++)    {        if (bz[i]==true) continue;        else        {            if (pd(i)==true) continue;            else             {                printf("%d\n",i-1);                return 0;            }        }    }    printf("%d\n",i-1);    return 0;    //那个bz数组只是一个我自认为可以加一加速度的判断数组而已,不用在意这些细节。}
好了,现在来说一说不会超时的简洁的短型代码吧!其实是这样的:f[i]表示的是凑成i分最少要多少张邮票,就是如下:
    for (i=1;i<=2000000;i++)    {        f[i]=666666666;        for (j=1;j<=n;j++)        {            if (i-a[j]>=0&&f[i]>f[i-a[j]]+1) f[i]=f[i-a[j]]+1;        }    }
十分简单明了,下面来看一看判断语句吧:
    if (f[i]>k)    {        printf("%d\n",i-1);        return 0;    }
是不是很简单,有没有想明白呢?其实,这些USACO的题目是比较适合那些需要提高思维能力的人去做的,因为只有做了以后,你才能在思维上有了质的飞越,希望多多思考,争取能够独立完成USACO的所有题!好了,废话也就说完了,下面来出一下完整代码:
#include<cstdio>using namespace std;int a[51],f[2000001];int k,n;int main(){    int i,j;    scanf("%d%d",&k,&n);    for (i=1;i<=n;i++)        scanf("%d",&a[i]);    for (i=1;i<=2000000;i++)    {        f[i]=666666666;        for (j=1;j<=n;j++)        {            if (i-a[j]>=0&&f[i]>f[i-a[j]]+1) f[i]=f[i-a[j]]+1;        }        if (f[i]>k)        {            printf("%d\n",i-1);            return 0;        }    }    printf("%d\n",i-1);    return 0;}
原创粉丝点击