POJ 1014 Dividing 这算是优化吗

来源:互联网 发布:网络渗透软件 编辑:程序博客网 时间:2024/04/30 01:52

给出n中m件商品,每件上面有自己的价格,问能否分成价格和相等的两堆。

设这m件商品的价值总和为s,则应有 (s&1) == 0 且 s >>= 1可达。

若只是单纯的将此多重背包转化成01背包,则时间复杂度为 m* (s>>=1) , 然后只看数据范围就知道要超时。

然后在《背包九讲》上看到了一个比较扯的关于只考虑可达性的完全背包的优化。

优化后的时间复杂度为 n*(s>>=1),但是我写完之后变成了 n*n*(s>>=1). . . . . .不过不要太当真。

总之这种方式只适合做 n 较小且只考虑可达性的完全背包。

设 f( i , j ) 表示只用前 i 种商品填充背包到达 j 时,第 i 种商品还剩多少件,-1表示此状态不可达。

递推代码如下:

for(i = 0;i < 6; ++i)   {                for(j = i+1;j <= sum; ++j)                {                    if(i == 0)                    {                        if(ans[0][j-1] > 0)                        {                            ans[0][j] = ans[0][j-1]-1;                        }                        else                            break;                    }                    else                    {                        for(int k = 0;k < i; ++k)                        {                            if(ans[k][j-i-1] >= 0)                            {                                ans[i][j] = a[i]-1;                            }                            if(ans[i][j-i-1] > 0)                            {                                ans[i][j] = max(ans[i][j],ans[i][j-i-1]-1);                            }                        }                    }                }            }



AC代码 在HDU跑时400+,在POJ只用32 . . . .果然什么事都不能太当真


#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <queue>#include <cmath>#include <algorithm>#include <stack>#define LL long long#define ULL unsigned long long#define PI (acos(-1.0))#define EPS (1e-10)#pragma comment(linker,"/STACK:102400000,1024000")using namespace std;int ans[6][120010];int main(){    int i,j,k,a[6],sum,t,s;    bool mark = true;    int icase = 1;    while(1)    {        for(sum = 0,i = 0,mark = false;i < 6; ++i)        {            scanf("%d",&a[i]);            if(a[i])            {                mark = true;                sum += a[i]*(i+1);            }        }        if(mark == false)            return 0;        printf("Collection #%d:\n",icase++);        if((sum&1) == 0)        {            sum >>= 1;            for(i = 0;i < 6; ++i)                memset(ans[i],-1,sizeof(int)*(sum+3));            for(i = 0;i < 6; ++i)            {                a[i] = min(a[i],sum/(i+1));                ans[i][0] = a[i];            }            for(i = 0;i < 6; ++i)            {                for(j = i+1;j <= sum; ++j)                {                    if(i == 0)                    {                        if(ans[0][j-1] > 0)                        {                            ans[0][j] = ans[0][j-1]-1;                        }                        else                            break;                    }                    else                    {                        for(int k = 0;k < i; ++k)                        {                            if(ans[k][j-i-1] >= 0)                            {                                ans[i][j] = a[i]-1;                            }                            if(ans[i][j-i-1] > 0)                            {                                ans[i][j] = max(ans[i][j],ans[i][j-i-1]-1);                            }                        }                    }                }            }            for(i = 0;i < 6; ++i)            {                if(ans[i][sum] != -1)                {                   break;                }            }            if(i < 6)                printf("Can be divided.\n\n");            else                printf("Can't be divided.\n\n");        }        else        {            printf("Can't be divided.\n\n");        }    }    return 0;}


0 0
原创粉丝点击