標籤:二進位 最佳化 多種背包 bfs dp
今天拉了一場CF,做了一下,略坑啊、、、首先105A題,竟然卡精度,小數點兩位卡精度,需要給他加一個1e-6,算是見識了
題目:Codeforces 106 C Buns
題意:給出一些n克面,以及m種餡兒,每種餡兒做麵包需要的面的克數和餡兒的克數以及餡兒的總克數,面也可以單獨做麵包,然後每一種麵包都有價格,求做的麵包的總價格最高?
分析:很賤的題目啊,讀了之後就開始貪心,貪心竟然過了10組資料,然後我以為有漏洞,後來發現是個多重背包。dp的題目最怕用貪心做了,幸虧發現了。
標準的多種背包,轉化一下就行了,n克面就是背包容量,然後每種的數量是餡兒的總量 / 每個的,花費是面的克數,價值是價格。剩下的事情就是模板了、二進位最佳化一下
AC代碼:
#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#include <map>#include <vector>using namespace std;const int inf = 0x3f3f3f3f;const int N = 1200;struct Node{ int cost,w,nk; //價格,重量,代數};Node num[N];int dp[N];//int cmp(Node a,Node b)//{// if(a.p!=b.p)// {// return a.p>b.p;// }//}void one(int cost , int w, int m){ for(int i=cost ; i<=m; i++) dp[i] = max(dp[i] , dp[i - cost ]+w);}void zero_one(int m ,int w, int cost){ for(int i=m; i>=cost; i--) dp[i]=max(dp[i],dp[i-cost]+w);}int main(){ int n,m,a,b; scanf("%d%d%d%d",&n,&m,&a,&b); num[0].nk=n/a,num[0].cost=b,num[0].w=a; for(int i=1; i<=m; i++) { int x,y,z,h; scanf("%d%d%d%d",&x,&y,&z,&h); num[i].nk=x/y; num[i].cost=h,num[i].w=z; } for(int i=0; i<=m; i++) { int w=num[i].cost , cost=num[i].w, nk=num[i].nk; if(cost * nk >= n) one(cost , w , n); else { int k = 1; while( k < nk) { zero_one(n,k*w,k*cost); nk -= k; k *= 2; } zero_one(n,nk*w,nk*cost); } } printf("%d\n",dp[n]); return 0;}
Codeforces 106 C Buns【多重背包】