UVA 10645-Menu(DP)

来源:互联网 发布:淘宝刷lol裁决靠谱吗 编辑:程序博客网 时间:2024/06/05 09:56

题目大意:Alfred要准备一些菜,每天一道菜,每个菜有收益和花费,如果连续两天准备同一道菜,收益减半,连续三天或更多,则不获得好感值,求在预算内的最多收益并输出每一天准备的菜。如果多个情况能获得相同的收益,输出花费较少的,如果还有多个,随意输出。


用d[i][j][u][0]表示前i天,花费至少j,第i天为第u道菜且第i-1天不为第u道菜时,最大的收益,

用d[i][j][u][1]表示前i天,花费至少j,第i天为第u道菜且第i-1天为第u道菜时,最大的收益。

a[u].cost和a[u].ben表示第u道菜的花费和收益。


对于d[i][j][u][0],由于它的前一天的菜不是u,所以找到前一天花费不超过j-a[u].cost,且最后一道菜(也就是第i-1天的菜)不是u时的最大收益是多少,就可以完成递推。

实际上只需要存储最大的3个收益值的信息(原因是3个中必然有一个的第i-1天的菜不和u相同)。在程序中用max[j][0],max[j][1],max[j][2]分别表示第一大,第二大,第三大收益值时的信息(当然也可以遍历一遍i-1天的情况,但这样复杂度升高)。max的第一维不用保存,每次运算完前两维时更新max数组。

对于d[i][j][u][1],它的前一天的菜是u,就由d[i-1][j-a[u].cost][u][0]或d[i-1][j-a[u].cost][u][1]递推而来。


程序将收益值乘2,在运算过程中避免浮点运算。

总体复杂度为O(n*m*k)


#include<stdio.h>#include<stdlib.h>typedef struct{int cost;int ben;}Coo;typedef struct{int num;int rep;int ben;}Maxt;Coo a[110];int b[110];Maxt max[110][3];int d[25][110][55][2];int pre[25][110][55][2][2];int main(void){int i,j,u,v,p,q,n,m,uu,vv,pp,qq,ans,min;scanf("%d%d%d",&n,&m,&p);while((n!=0)||(m!=0)||(p!=0)){min=(1<<30);for(i=1;i<=m;i++){scanf("%d%d",&u,&v);a[i].cost=u;a[i].ben=v*2;min=(u<min)?u:min;}if(min*n>p){printf("0.0\n");}else if(m==1){ans=a[1].ben+a[1].ben/2;printf("%d.%d\n",ans/2,ans%2==0?0:5);printf("1");for(i=2;i<=n;i++){printf(" 1");}printf("\n");}else{for(j=1;j<=p;j++){max[j][0].ben=max[j][1].ben=max[j][2].ben=-(1<<30);for(u=1;u<=m;u++){v=j-a[u].cost;d[1][j][u][1]=-(1<<30);if(v<0){d[1][j][u][0]=-(1<<30);}else{d[1][j][u][0]=a[u].ben;}if(d[1][j][u][0]>max[j][0].ben){max[j][2]=max[j][1];max[j][1]=max[j][0];max[j][0].ben=d[1][j][u][0];max[j][0].rep=0;max[j][0].num=u;}else if(d[1][j][u][0]>max[j][1].ben){max[j][2]=max[j][1];max[j][1].ben=d[1][j][u][0];max[j][1].rep=0;max[j][1].num=u;}else if(d[1][j][u][0]>max[j][2].ben){max[j][2].ben=d[1][j][u][0];max[j][2].rep=0;max[j][2].num=u;}}}for(i=2;i<=n;i++){for(j=1;j<=p;j++){for(u=1;u<=m;u++){v=j-a[u].cost;if(v<=0){d[i][j][u][0]=d[i][j][u][1]=-(1<<30);}else{if(max[v][0].num!=u){d[i][j][u][0]=max[v][0].ben+a[u].ben;pre[i][j][u][0][0]=max[v][0].num;pre[i][j][u][0][1]=max[v][0].rep;}else if(max[v][1].num!=u){d[i][j][u][0]=max[v][1].ben+a[u].ben;pre[i][j][u][0][0]=max[v][1].num;pre[i][j][u][0][1]=max[v][1].rep;}else{d[i][j][u][0]=max[v][2].ben+a[u].ben;pre[i][j][u][0][0]=max[v][2].num;pre[i][j][u][0][1]=max[v][2].rep;}if(d[i-1][v][u][0]+a[u].ben/2>d[i-1][v][u][1]){d[i][j][u][1]=d[i-1][v][u][0]+a[u].ben/2;pre[i][j][u][1][0]=u;pre[i][j][u][1][1]=0;}else{d[i][j][u][1]=d[i-1][v][u][1];pre[i][j][u][1][0]=u;pre[i][j][u][1][1]=1;}}}}for(j=1;j<=p;j++){max[j][0].ben=max[j][1].ben=max[j][2].ben=-(1<<30);for(u=1;u<=m;u++){if(d[i][j][u][0]>max[j][0].ben){max[j][2]=max[j][1];max[j][1]=max[j][0];max[j][0].ben=d[i][j][u][0];max[j][0].rep=0;max[j][0].num=u;}else if(d[i][j][u][0]>max[j][1].ben){max[j][2]=max[j][1];max[j][1].ben=d[i][j][u][0];max[j][1].rep=0;max[j][1].num=u;}else if(d[i][j][u][0]>max[j][2].ben){max[j][2].ben=d[i][j][u][0];max[j][2].rep=0;max[j][2].num=u;}if(d[i][j][u][1]>max[j][0].ben){max[j][2]=max[j][1];max[j][1]=max[j][0];max[j][0].ben=d[i][j][u][1];max[j][0].rep=1;max[j][0].num=u;}else if(d[i][j][u][1]>max[j][1].ben){max[j][2]=max[j][1];max[j][1].ben=d[i][j][u][1];max[j][1].rep=1;max[j][1].num=u;}else if(d[i][j][u][1]>max[j][2].ben){max[j][2].ben=d[i][j][u][1];max[j][2].rep=1;max[j][2].num=u;}}}}ans=-(1<<30);for(j=1;j<=p;j++){for(u=1;u<=m;u++){if(d[n][j][u][0]>ans){uu=u;vv=0;q=j;ans=d[n][j][u][0];}if(d[n][j][u][1]>ans){uu=u;vv=1;q=j;ans=d[n][j][u][1];}}}for(i=n;i>=1;i--){b[i]=uu;pp=pre[i][q][uu][vv][0];qq=pre[i][q][uu][vv][1];u=q-a[uu].cost;uu=pp;vv=qq;q=u;}printf("%d.%d\n",ans/2,ans%2==0?0:5);printf("%d",b[1]);for(i=2;i<=n;i++){printf(" %d",b[i]);}printf("\n");}scanf("%d%d%d",&n,&m,&p);}return 0;}


0 0