"Dynamic Programming · backpack" Gift

Title Description

Here Insert Picture Description

answer

If the current first i i th item is not selected and not selected article is minimal, then this means that a volume of less than a i a_i When there will be no other items to fill a backpack, then finished conducted for other items 01 backpack after contributed answer is: i = m a i + 1 m f [ i ] \sum_{i=m-a_i+1}^{m}f[i] .

But doing so there are two difficulties: time complexity are not good enough, and can not guarantee whether the items are currently no election is the smallest of items.

So we enumerate whether a point is a minimum of time, make it a point not to force the election, it is smaller than both the election, it looks larger than pick cases.

We use to think with O ( n 2 ) O (n ^ 2) level algorithm. Obviously, the answer is divided into two parts:

  • Than this point to do 01 backpack big volume.
  • Small size than this point forcibly selected.

At this point we need to sort descending, not to omit the first dimension state, we can get a large volume of the backpack portion 01 results.

Very simple transfer equation is: f [ i ] [ j ] = f [ i 1 ] [ j ] + f [ i 1 ] [ j a [ i ] ] f[i][j]=f[i-1][j]+f[i-1][j-a[i]]

Then forcibly select one item, forced state transition according to the backpack 01 is formed larger items, other S = j = i + 1 m a j S=\sum_{j=i+1}^{m} a_j .

It can be transferred, set up g [ i ] g[i] indicates a mandatory selection of i + 1 i+1 after the program items: g [ j ] = f [ i 1 ] [ j S ] g[j]=f[i-1][j-S]

Then the answer is: a n s   =   i = 1 n j = m a + i + 1 m g j ans\ =\ \sum_{i=1}^{n} \sum_{j=m-a+i+1}^{m} g_j

code show as below:

#include <bits/stdc++.h>

#define int long long

using namespace std;
const int N = 2000;
const int P = 1000000007;

int n, m, ans = 0;
int a[N], f[N][N], s[N];

signed main(void)
{
	cin>>n>>m;
	for (int i=1;i<=n;++i) cin>>a[i];
	sort(a+1,a+n+1);
	reverse(a+1,a+n+1);//从大到小排序 
	f[0][0] = 1;
	for (int i=1;i<=n;++i)
	    for (int j=0;j<=m;++j)
	    {
	        if (j >= a[i]) f[i][j] = (f[i-1][j]+f[i-1][j-a[i]]) % P;//01背包 
	        else f[i][j] = f[i-1][j];
	    }
	for (int i=n;i>=1;--i) s[i] = s[i+1]+a[i];//后缀和 
	for (int i=1;i<=n;++i)
	{
		//枚举强制不选择的物品
		//强制选择i+1-n的物品
		int v = s[i+1];
		int g[10000] = {};
		for (int j=m;j>=v;--j) g[j] = f[i-1][j-v];
		for (int j=m-a[i]+1;j<=m;++j) ans = (ans+g[j]) % P;
	}
	cout<<ans<<endl;
	return 0;
}

to sum up:

This title challenge is to think of how to answer a total and pass a minimum-related, then you can fool around various optimization.

Guess you like

Origin blog.csdn.net/Ronaldo7_ZYB/article/details/94755958