状态转移方程貌似是可以想得到,但是有点不知道怎么实行,估计是理解不够深入。。。。。
可以先贴个代码吗?。。。
**************************************
问了下学长。。。。。。总的没有错(怎么有点高兴~~)但是还有一些地方要注意(完全没想法之……一些地方……)
总的说下,dp[i][j][0/1]表示前i个物品取j个,当前这个物品取还是不取。
那么就可以得到dp[i][j][0]=min(dp[i-1][j][0],dp[i-1][j][1]),dp[i][j][1]=min(dp[i-1][j-1][0]+f,dp[i-1][j-1][1]+c),f和c表示之前那个物品取和不取造成的不同的流量。
若到此就好了!!
但是!!这里每个包的大小可以比文件的大!!那么这样的话就会造成状态没有办法转移!!
所以……我就不知道要怎么办了……
#include <stdio.h>
#include <string.h>
#define maxn 3010
int dp[maxn][maxn][2];
int f[maxn],c[maxn],s[maxn];
int max(int x,int y)
{
if(x>y) return x;
else return y;
}
int min(int x,int y)
{
if(x>y) return y;
else return x;
}
int main()
{
int n,m,l;
while(scanf("%d%d%d",&n,&m,&l)!=EOF&&n+m+l)
{
int i,j,k;
int ans,sum;
int tmp=0;
memset(c,0,sizeof(c));
memset(dp,0,sizeof(dp));
memset(s,0,sizeof(s));
for(i=1;i<n;i++)
{
scanf("%d",&f[i]);
// printf("tmp=%d\n",tmp);
if(tmp)
c[i]+=m;
if((f[i]-tmp)%m)
{
c[i]+=(f[i]-tmp)/m*m;
c[i]+=m;
tmp=m-(f[i]-tmp-(f[i]-tmp)/m*m);
}
else c[i]+=f[i]-tmp;
s[i]=s[i-1]+f[i];
}
scanf("%d",&f[n]);
if(tmp) c[n]+=m;
c[n]+=f[n]-tmp;
// for(i=1;i<=n;i++) dp[i][1][1]=c[i];
// for(i=1;i<=n;i++) printf("%d ",c[i]); printf("\n");
for(i=1;i<=n;i++)
{
dp[i][0][0]=l;
for(j=1;j<=i;j++)
{
dp[i][j][0]=min(dp[i-1][j][1],dp[i-1][j][0]);
dp[i][j][1]=min(dp[i-1][j-1][0]+c[j],dp[i-1][j-1][1]+s[j-1]%m?-m:0+c[j]);
printf("%d %d %d %d\n",dp[i][j][0],dp[i][j][1],i,j);
}
}
for(i=n;i>=0;i--)
if(dp[n][i][0]<=l&&dp[n][i][0]>0)
{ans=i;break;}
for(i=n;i>=0;i--)
if(dp[n][i][1]<=l&&dp[n][i][1]>0)
{
sum=i;break;
}
printf("%d\n",max(ans,sum));
}
return 0;
}