北大ACM——3046,Ant Counting(DP)

题意:有T种蚂蚁,总共A只,求将这些蚂蚁,分为数量为S,S+1,S+2,…,B的集合的总集合数。
突破口:
设置a[T]记录每种蚂蚁的数量,设置dp[i,j]表示,用前i种蚂蚁,构成数量为j的集合的最大集合数,那么,第i种蚂蚁有用0只,1只,…,a[T]只,因此,状态转移方程应为:
dp[i,j]=sum(dp[i-1,j~j-a[T]]).

代码如下:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=1e5+5,mod=1e6;
int dp[maxn],a[1005];		//注意,这里要用滚动数组,否则很可能会爆内存
int main()
{
	int T,A,S,B,i,j,k;
	int sum=0;
//	printf("%d\n",mod);		//哎呀,mod要等于1e6,一开始弄成1e7,找了好一段时间的bug
	scanf("%d%d%d%d",&T,&A,&S,&B);
	for(i=0;i<=T;i++)
		a[i]=0;
	for(int t,i=1;i<=A;i++)
	{
		scanf("%d",&t);
		a[t]++;
		dp[i]=0;
	}
	for(i=0;i<=a[1];i++)
		dp[i]=1;
	for(i=2;i<=T;i++)
	{
		for(j=B;j>=1;j--)
		{
			int sum1=0;
			for(k=j;(k>=0)&&(k>=j-a[i]);k--)
				sum1=(sum1+dp[k])%mod;
			dp[j]=sum1%mod;
		}
	 }
	for(i=S;i<=B;i++)
		sum=(sum+dp[i])%mod;		//记得取模
	printf("%d\n",sum);
	return 0;
}

TIPS:没什么思路的时候可以手推,然后划出一个表来观察。一开始这么找到状态转移方程的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值