ZOJ - 3682
有 S1 个球迷支持巴萨, S2 个球迷支持皇马
球场有 N 个方阵,每个可以坐ki 个球迷
安排球迷使得一个方阵要么全是支持巴萨的
要么全是支持皇马的,要么两种相等
问有几种安排方案
其实一看
N
最多只有200,但是
然后就开了一个 map,结果依旧是爆空间了 (这题空间只有 65M)
所以只好老老实实地滚动数组了
因为确定了
S1
,那么
S2
也可以确定,所以只要
S1
存一维就好
剩下的用类似背包DP的转移方式去转移就好了
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std;
typedef pair<int,int> Pii;
typedef long long LL;
typedef unsigned long long ULL;
typedef double DBL;
typedef long double LDBL;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Pow2(a) (a*a)
const int MOD=1000000007,maxs=1e5+10;
int S1,S2,N;
int inpt[210],psum[210];
LL dp[maxs];
int main()
{
while(~scanf("%d%d%d", &S1, &S2, &N))
{
CLR(dp);
dp[0]=1;
for(int i=1; i<=N; i++)
{
scanf("%d", &inpt[i]);
psum[i]=psum[i-1]+inpt[i];
}
for(int i=1; i<=N; i++)
{
for(int s1=S1; s1>=0; s1--)
{
int s2=S2-(psum[i-1]-s1);
LL pre=dp[s1];
dp[s1]=0;
if(s1>=inpt[i]) dp[s1]+=dp[s1-inpt[i]];
if(s2>=inpt[i]) dp[s1]+=pre;
if(!(inpt[i]&1)&&s1>=inpt[i]/2&&s2>=inpt[i]/2) dp[s1]+=dp[s1-inpt[i]/2];
dp[s1]%=MOD;
}
}
printf("%lld\n", dp[S1]);
}
return 0;
}