题意: 有巴塞罗纳和马德里球迷s1,s2。同时有n个广场,每个广场能容纳一定的球迷。为了让比赛是和谐的,所以要分配两边的球迷入座这n个广场。对于单个广场,只有三中情况是和谐的:1.全是巴塞罗纳球迷 2.全是马德里球迷 3.各占一半 。当n个广场是和谐的时候,比赛就是和谐的了。问:使得比赛和谐的入座方案数是多少。
思路: 可以把人数看成容量,广场的容量看成花费。dp[i][j]表示前i个广场j个球迷的方案数,那么这就是一个01背包,但是有点不一样,它有三种转移,而且有一种转移要用到dp[i-1][v],所以不能像01背包那样优化到单纯的一维。但是可以用滚动数组,所以内存还是够的。
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 100100
int square[220],dp[2][N];
const int MOD=1000000007;
int main()
{
using namespace std;
int i,s1,s2,n,v,cur,pre;
while(~scanf("%d %d %d",&s1,&s2,&n)){
for(i=0;i<n;i++) scanf("%d",&square[i]);
memset(dp,0,sizeof(dp));
cur=0,pre=1;
dp[cur][0]=1;
for(i=0;i<n;i++){
swap(cur,pre);
memset(&dp[cur][0],0,(s1+1)*sizeof(dp[0][0]));
for(v=0;v<=s1;v++){
dp[cur][v]=(dp[cur][v]+dp[pre][v])%MOD;
if(v>=square[i])
dp[cur][v]=(dp[cur][v]+dp[pre][v-square[i]])%MOD;
if(square[i]%2==0 && v>=square[i]/2)
dp[cur][v]=(dp[cur][v]+dp[pre][v-square[i]/2])%MOD;
}
}
printf("%d\n",dp[cur][s1]);
}
return 0;
}