现在的位置: 首页 > 综合 > 正文

poj 1276Cash Machine(多重背包, 二进制划分)

2013年07月10日 ⁄ 综合 ⁄ 共 728字 ⁄ 字号 评论关闭

                     赤裸裸的多重背包问题;

方法一:直接三重循环,这种方法会超时地……

for(i=1; i<=n; i++)
{
	for(j=cash; j>=dk[i]; j--)
	{
		for(k=1; k<=nk[i]; k++)
		{
			if( j<k*dk[i]) break;
			if( dp[j]<dp[j-k*dk[i]]+k*dk[i])
				dp[j]=dp[j-k*dk[i]]+k*dk[i];
		}
	}
}

方法二:二进制划分,将同种物品,以二进制划分的方式合并,大大减少了物品数量,然后以0 1背包的方法……

代码如下:

#include<stdio.h>
#include<string.h>
int main()
{
    int cash, n;
    int dk[11], nk[11],dp[100001];
	int i, j, k, temp;
    while( scanf("%d %d", &cash, &n)!=EOF )
	{
		memset(dp, 0, sizeof(dp));
        for(i=1; i<=n; i++)
			scanf("%d %d", nk+i, dk+i);
		for(i=1; i<=n; i++)
		{
			for(k=1; k<=nk[i]; k*=2)//二进制划分
            {
                nk[i]-=k;
				temp=k*dk[i];
				for(j=cash; j>=temp; j--)//0,1背包
				{
					if(  dp[j]<dp[j-temp]+temp)
						dp[j]=dp[j-temp]+temp;
				}
            }
			if( nk[i]>0 )
			{
				temp=nk[i];*dk[i];
				for(j=cash; j>=temp; j--)//0,1背包
				{
					if(  dp[j]<dp[j-temp]+temp)
						dp[j]=dp[j-temp]+temp;
				}
			}
		}
		printf("%d\n",dp[cash]);
	}
}

抱歉!评论已关闭.