【codeforces 946D】Timetable(預處理+分組揹包)
阿新 • • 發佈:2018-12-24
=-=以前揹包沒學好。。。居然是第一次做分組揹包的題,咳咳 不過這題比較厲害的是它的預處理。。。心態崩了,為什麼有的時候一個回車會往下走這麼多行想刪回車,一下子就刪了一段,還不知道在哪撤回mmp,就寫一丟丟列舉左右端點可以一起移動要令value[i][num[i]]=m然後揹包的第二個迴圈是從大到小,不然就相當於在這一類物品中拿了多個東西程式碼程式碼。。。生氣
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;
const int inf=999999999;
int dp[600],num[600],fin[600][600],value[600][600];
int main()
{
int n,m,v;
while(~scanf("%d%d%d",&n,&m,&v))
{
for(int i=1;i<=n;i++)//輸入
{
int t=0;
for(int j=1;j<=m;j++)
{
//printf("test\n");
char a;
scanf(" %c",&a);
if(a=='1')fin[i][++t]=j;//fin[i][j]存第i天第j節課在第幾節
}
num[i]=t;//num[i]儲存第i天課的數量
}
for(int i=1;i<=n;i++)//計算value,即第i天翹n節課節約的最大時間
{
for(int j=0;j<=min(num[i],v);j++)
{
int res=inf;
int p,q;
for(int k=0;k<=j;k++)
{
p=k;q=j-k;//列舉左右端點,即左縮排p位右縮排q位
res=min(res,fin[i][num[i]-q]-fin[i][p+1]+1);
}
value[i][j]=m-res;
//printf("%d\n",value[i][j]);
}
value[i][num[i]]=m;
}
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)//揹包部分
{
for(int j=v;j>=0;j--)
{
//printf("% [email protected]\n",j);
for(int k=0;k<=min(num[i],j);k++)
{
dp[j]=max(dp[j],dp[j-k]+value[i][k]);//dp[i]為翹i節課能節約的最大時間
}//printf("%d\n",dp[j]);
}
}
printf("%d\n",n*m-dp[v]);
}
return 0;
}
=-=