度度熊的午饭时光
2017-08-07 07:57
113 查看
题目描述
度度熊最期待每天的午饭时光,因为早饭菜品清淡,晚饭减肥不敢吃太多(胖纸的忧伤T.T)。百度食堂的午餐超级丰富,祖国各大菜系应有尽有,度度熊在每个窗口都有爱吃的菜品,而且他还为喜爱的菜品打了分,吃货的情怀呀(>.<)。
但是,好吃的饭菜总是很贵,每天的午饭预算有限,请帮度度熊算一算,怎样打饭才能买到的最好吃的饭菜?(不超过预算、不重样、午餐等分最高的情况下,选择菜品序号加和最小,加和相等时字典序最小的组合)
题目分析
这一道题就是典型的背包DP。我们可以设一下bz[i]这个布尔数组为是否能刚好用掉i元钱,然后用一个辅助布尔数组,bz2[i][j]表示在刚好花掉i元钱,最优方案的时候第j个菜是否会被选中。
接着我们便会得到一个转移方程。
如果bz[i-c[j]]的方案比bz[i]好,
bz2[i]=bz2[j]。
但问题是,我们怎么判断bz[i-c[j]]的方案是否会比bz[i]好呢?
首先我们先判断一下他们的分数(注意,bz[i-c[j]]的所有分数和加起来后还要加是s[j]!),如果分数相同,我们就看一下他们的编号和(也别忘了加j!)如果编号和相同,我们就看一下他们的字典序是否相等,哪个更小就选哪一个。
最后选择所有方案中最优的方案。
代码
#include<cstdio> #include<cstring> using namespace std; bool bk[1100][110],bz[1100]; int s[1100],c[1100]; int b,n; int sum7[110],sum8[110]; int ans3[110]; int mymin(int x,int y) {return x<y?x:y;} void insert(int cost,int id) { if(bz[cost]==false) { bz[cost]=true; for(int i=1;i<=n;i++) { bk[cost][i]=bk[cost-c[id]][i]; } bk[cost][id]=true; return ; } if(bk[cost-c[id]][id]==true) { return ; } int sum=0,sum2=0,sum3=0,sum4=0,sum5=0,sum6=0; for(int i=1;i<=n;i++) { if(bk[cost-c[id]][i]==true) { sum+=i; sum3+=s[i]; sum5++; sum7[sum5]=i; } if(bk[cost][i]==true) { sum2+=i; sum4+=s[i]; sum6++; sum8[sum6]=i; } } sum5++; sum7[sum5]=id; bool bk2=false; if(sum+id<sum2) bk2=true; if(sum+id==sum2) { bool bz2=false; for(int i=1;i<=mymin(sum5,sum6);i++) { if(sum7[i]<sum8[i]) { bz2=true; bk2=true; break; } if(sum7[i]>sum8[i]) { bz2=true; break; } } if(bz2==true&&sum5>sum6) { bk2=true; } } if(sum3+s[id]>sum4||(bk2==true&&sum3+s[id]==sum4)) { for(int i=1;i<=n;i++) { bk[cost][i]=bk[cost-c[id]][i]; } bk[cost][id]=true; } return ; } int main() { freopen("d.in","r",stdin); freopen("d.out","w",stdout); int t,t2=0; scanf("%d",&t); while(t--) { scanf("%d",&b); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d",&s[i],&c[i]); } memset(bz,false,sizeof(bz)); memset(bk,false,sizeof(bk)); bz[0]=true; for(int i=1;i<=n;i++) { for(int j=b;j>=c[i];j--) { if(bz[j-c[i]]==true) { insert(j,i); } } } int ans=-1,ans2; for(int i=0;i<=b;i++) { int sum9=0; for(int j=1;j<=n;j++) { if(bk[i][j]==true) { sum9+=s[j]; } } bool bk2=false; if(sum9==ans) { int sum=0,sum2=0,sum3=0,sum4=0,sum5=0,sum6=0; for(int j=1;j<=n;j++) { if(bk[i][j]==true) { sum+=j; sum3+=s[j]; sum5++; sum7[sum5]=j; } if(bk[ans2][j]==true) { sum2+=j; sum4+=s[j]; sum6++; sum8[sum6]=j; } } if(sum<sum2) bk2=true; if(sum==sum2) { bool bz2=false; for(int j=1;j<=mymin(sum5,sum6);j++) { if(sum7[j]<sum8[j]) { bz2=true; bk2=true; break; } if(sum7[j]>sum8[j]) { bz2=true; break; } } if(bz2==false&&sum5>sum6) { bk2=true; } } } if(sum9>ans||(sum9==ans&&bk2==true)) { ans=sum9; ans2=i; } } printf("Case #%d:\n",++t2); printf("%d %d\n",ans,ans2); int len=0; for(int i=1;i<=n;i++) { if(bk[ans2][i]==true) { len++; ans3[len]=i; } } for(int i=1;i<=len;i++) { if(i<len) printf("%d ",ans3[i]); else printf("%d\n",ans3[i]); } } return 0; }
相关文章推荐
- 度度熊的午饭时光 2017百度之星
- 2017百度之星资格赛 hdu6083 度度熊的午饭时光 (01背包+字典序路径)
- hdu 6083 度度熊的午饭时光(01背包+打印路径)
- “百度之星”资格赛 1004 度度熊的午饭时光
- 度度熊的午饭时光[2017百度之星资格赛 1004]
- hdu 6083 度度熊的午饭时光(01背包+打印路径)
- 2017百度之星资格赛:1004. 度度熊的午饭时光(01背包+记录路径)
- HDU 6083 度度熊的午饭时光(01背包+记录路径)
- hdu 6083 度度熊的午饭时光(01背包+打印路径)
- 百度之星 度度熊的午饭时光
- HDU - 6083 度度熊的午饭时光 (记录路径的01背包)
- hdu 6083 度度熊的午饭时光(01背包+打印路径)
- 1004 度度熊的午饭时光<01 背包>
- hdu 6083 度度熊的午饭时光(01背包+打印路径)
- hdu6083 2017"百度之星"资格赛1004 度度熊的午饭时光(背包dp+记录路径)
- 01背包&&打印路径(hdu6083)度度熊的午饭时光
- hdu 6083 度度熊的午饭时光(01背包+打印路径)
- 度度熊的午饭时光——01背包
- [HDOJ6083] 度度熊的午饭时光(背包,记录路径)
- 百度之星1004度度熊的午饭时光