1. 程式人生 > >焦作網路預選賽K題-多重揹包

焦作網路預選賽K題-多重揹包

題目大意就是給你n種船,每種船的數量和運載能力,問s噸貨物可以有多少種運輸方式?

題意很明顯就是多重揹包,甚至還有點像硬幣那道題HDU1284,所以順著那道題的思路來就行了,在那道題中,是這種方法做出來的,其中i代表硬幣的價值,j代表著總價值。

void solve()
{
    dp[0]=1;
    for(int i=1;i<=3;i++)
    {
        for(int j=i;j<=32768;j++)
        {
            dp[j]+=dp[j-i];
        }
    }
}

而在本題中因為給定了每種船的數量,於是儲存每種船使用i艘時的載貨量,然後等同於上面的硬幣之,那麼就可以類推出來這道題的程式碼。

程式碼:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e4 + 10;
const int mod = 1000000007;
int dp[maxn];
int num[maxn];
int pows[25];

int main()
{
		pows[0] = 1;
		for (int i = 1; i <= 20; i++)
		{
				pows[i] = pows[i - 1] * 2;
		}
		int t;
		scanf("%d", &t);
		while (t--)
		{
				memset(dp, 0, sizeof(dp));
				int n, q;
				scanf("%d %d", &n, &q);
				int tot = 0;
				for (int i = 0; i < n; i++)
				{
						int a, b;
						scanf("%d %d", &a, &b);
						for (int j = 0; j <= b - 1; j++)
						{
								num[tot++] = (pows[j] * a)%mod;
						}
				}
				dp[0] = 1;
				for (int i = 0; i < tot; i++)
				{
						for (int j = 1e4; j >= num[i]; j--)
						{
								dp[j] = (dp[j] + dp[j - num[i]]) % mod;//這裡一定是從1e4開始遞減的,具體的請看我部落格裡有一篇部落格講到了這個就是那篇模板簡記的那篇。
						}
				}
				while (q--)
				{
						int quer;
						scanf("%d", &quer);
						printf("%d\n", dp[quer]);
				}
		}
		return 0;
}