您的位置:首页 > 其它

分糖果

2015-10-11 18:33 190 查看
f[i][j][k]表示前i个糖果,取了j个,ri和fi的差值为k时的最大和,转移时有三种情况,不取,增大差值,减小差值。注意不要越界,一开始的差值为0可以用400来表示,这样不会让数组出现负的下标,f[i][j][k]=MAX(f[i-1][j][k],f[i-1][j-1][k-(r[i]-f[i])]+r[i]+f[i]),如果f[i][j][k]上被更新过,则代表有这种可能性,所以答案为f
[m][k-i],i=0,1,2….找到i最小的被更新过的位置则为答案。

自己一开始用的f[i][j]表示前i个取j个的最小k值,同时另开两个数组表示cigma(r,f),

但是忽略了这样做的后效性。

#include<cstdio>
#include<cstring>
using namespace std;
int m,n;
int f[205][22][821];
int MAX(int a,int b){
if(a>b) return a;
else return b;
}
int r[205],l[205];
int ABS(int x,int y){
x-=y;
return -x;
}
int main(){

memset(f,-0x3f,sizeof(f));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d%d",&l[i],&r[i]);
f[i][0][400]=0;
}
f[0][0][400]=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(j>i) break;
for(int k=10;k<=800;k++){
f[i][j][k]=MAX(f[i-1][j-1][k-(l[i]-r[i])]+r[i]+l[i],f[i-1][j][k]);
//        if(f[i][j][k]>0) printf("f[%d][%d][%d] =%d\n",i,j,k,f[i][j][k]);
}
}
}
for(int i=0;i<=400;i++){
if(f
[m][400+i]>0&&f
[m][400-i]>0){
printf("%d\n%d",i,MAX(f
[m][400-i],f
[m][400+i]));
break;
}
if(f
[m][400+i]>0){
printf("%d\n%d",i,f
[m][400+i]);
break;
}
if(f
[m][400-i]>0){
printf("%d\n%d",i,f
[m][400-i]);
break;
}
}
//    printf("\n%d\n",f[1][1][399]);
getchar(); getchar();
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: