2010-1144
从 Trac 迁移的文章
这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。
原文章内容如下:
题目大意是HH要bg他的n个朋友,第i个朋必须友要在di天前bg,每天最多只能bg一个朋友。[[BR]]
动态规划,设f[j][k]表示前k天bg前j个朋友,显然第i个朋友最早可以bg的时间是第i天。动态转移方程 f[j][k]= sigma( f[j-1][i] )(j-1 <= i <= k-1), 初始值f[0][0]=1。[[BR]]
可以使用滚动数组优化,但每次要memset为0。[[BR]]
可以使用两个小优化,一个是缩小di的范围,一个是判断是否有解。
{{{
#!cpp
#include<cstdio>
#include<cstring>
long f[2][20001];
int main()
{
long n,j,k,i,t,a[501];
while(scanf("%ld",&n)!=EOF)
{
for (j=1;j<=n;++j) scanf("%ld",&a[j]);
for (j=n;j>1;--j) if (a[j]-1<a[j-1]) a[j-1]=a[j]-1;//优化范围
if (a[1]<=0) { printf("0\n"); continue; } //判断是否存在可行解没有则直接输出
memset(f,0,sizeof(f));f[0][0]=1;
for (j=1;j<=n;++j)
{
memset(f[j&1],0,sizeof(f[j&1]));
i=f[(j-1)&1][j-1]%100000009;
for (k=j;k<=a[j];++k)
{
f[j&1][k]=i;
i=(i+f[(j-1)&1][k])%100000009;
}
}
i=0;
for (j=n;j<=a[n];++j) i= (i+f[n&1][j])%100000009;
printf("%ld\n",i);
}
return 0;
}
}}}
题目大意是HH要bg他的n个朋友,第i个朋必须友要在di天前bg,每天最多只能bg一个朋友。
动态规划,设f[j][k]表示前k天bg前j个朋友,显然第i个朋友最早可以bg的时间是第i天。动态转移方程 f[j][k]= sigma( f[j-1][i] )(j-1 <= i <= k-1), 初始值f[0][0]=1。
可以使用滚动数组优化,但每次要memset为0。
可以使用两个小优化,一个是缩小di的范围,一个是判断是否有解。
#include<cstdio>
#include<cstring>
long f[2][20001];
int main()
{
long n,j,k,i,t,a[501];
while(scanf("%ld",&n)!=EOF)
{
for (j=1;j<=n;++j) scanf("%ld",&a[j]);
for (j=n;j>1;--j) if (a[j]-1<a[j-1]) a[j-1]=a[j]-1;//优化范围
if (a[1]<=0) { printf("0\n"); continue; } //判断是否存在可行解没有则直接输出
memset(f,0,sizeof(f));f[0][0]=1;
for (j=1;j<=n;++j)
{
memset(f[j&1],0,sizeof(f[j&1]));
i=f[(j-1)&1][j-1]%100000009;
for (k=j;k<=a[j];++k)
{
f[j&1][k]=i;
i=(i+f[(j-1)&1][k])%100000009;
}
}
i=0;
for (j=n;j<=a[n];++j) i= (i+f[n&1][j])%100000009;
printf("%ld\n",i);
}
return 0;
}