摆花

2 篇文章 0 订阅

在这里插入图片描述

思路1:暴搜–>骗分 //由于过于SB 本人不做演示

思路2:DP

设f[i][j]为用前i个数摆j盆且以i结尾的所有可能性
则可以发现:当第k~j盆摆放i时则可能的方案数为f[i-1][k-1]       //k为1~j中的某一个位置
           而k可以为1~j中的任何一个

则f[i][j]=第1行第j-a[i]列到第i-1行第j-1列这个矩阵的和

你们认为这就完了么??? 不当然不!!!
举个栗子:

输入:
3  4
3  2  2

模拟f数组:

       1  2  3  4           第j列
     
1      1  1  1  _
2      1  2  2  2
3      1  3  5  6
第
i
行

以第3行第2列为例
f[3][2]=f[1][1]+f[2][1]=1+1=2 ???
但事实上却等于3 why???
我们列一下:
当第2盆摆3时,则有两种可能: (1,3),(2,3)
当第一种和第二种都摆3时,则有一种可能: (3,3)
但当第一种和第二种都摆3时,我们却未算进去

所以:

if (a[i]>=j) f[i][j]++;

so…
代码:

const int N=110,mod=1000007;
int ans,n,m,a[N],f[N][N];
int find (int x,int y)
{
	int ans(0);
	for (int i=1;i<=x-1;i++) for (int j=y-a[x];j<=y-1;j++) ans+=f[i][j],ans%=mod;
	return ans%mod;
}

int main ()
{
	scanf ("%d %d",&n,&m);
	for (int i=1;i<=n;i++) scanf ("%d",&a[i]);
	for (int i=1;i<=n;i++)
	{
		for (int j=1;j<=m;j++)
		{
			f[i][j]=find (i,j);
			if (a[i]>=j) f[i][j]=(f[i][j]+1)%mod;
			//printf ("%d ",f[i][j]);
		}
		//printf ("\n");
	}
	for (int i=1;i<=n;i++) ans=(ans+f[i][m])%mod;
	printf ("%d",ans);                     //输出为f[1][m]~f[n][m]的和
	return 0;
}

但看一下时间复杂度:O(N2 *M2 )=108 勉强能过

但我们再看看:

对于f[i][j],它等于第1行第j-a[i]列到第i-1行第j-1列这个矩阵的和

则我们可以用二维前缀和优化!!!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值