动态规划 HDU 2546 饭卡

来源:互联网 发布:适合男生用的面膜知乎 编辑:程序博客网 时间:2024/06/08 15:49

        在acm群里看到了这样的一个题目,拿过来看了一下,感觉还蛮有意思的,题目大意是饭卡上有m余额,但是学校有个规定,饭卡余额少于5元就不能买东西,现在有n件商品,每件商品都有一个价格。要求买好商品后余额最少。

        题目链接   HDU 2546 饭卡

        看到题目就想到了背包问题,在一个m-5的背包里尽量装满东西,装满后放最后一个物品,解肯定在放完这个物品之后。 最直接的想法就是对放的最后这个物品进行枚举,然后用余下的物品去装m-5的背包,尽量装满。得到的最小值就是答案。当然还要考虑余额小于5元的情况,如果小于5元就直接输出就行了,因为不能买东西。

        思路有了,接下去是实现,n是1000,m是1000,价格不会超过50,如果枚举的话,复杂度是n*n*m,明显会超时。由于每件商品价格不会超过50,那么只要统计下对应价格的商品件数就行了,然后用二进制优化。

       帖代码:

     

#include <iostream>#include <algorithm>using namespace std;#define INF 0xFFFFFFFint price[55]; //统计对应价格的商品件数int dp[1001],m;void zeroOnePack(int volume){for (int k=m-5; k>=volume; k--){dp[k] = max(dp[k], dp[k-volume]+volume);}}int main(){int  n, p;while (cin >> n && n ){memset(price, 0, sizeof(price));for (int i=0; i<n; i++){cin >> p;price[p] ++ ;}cin >> m;if (m <5) { cout << m << endl; continue; }int ans = INF;for (int i=1; i<=50; i++){if (!price[i]) continue;price[i] --;memset(dp, 0, sizeof(dp));for (int j=1; j<=50; j++){if (!price[j]) continue;int total = price[j];for (int gs=1 ; total>=gs; gs<=1, total-= gs){zeroOnePack(gs*j);}zeroOnePack(total*j);}int tmp = m-dp[m-5]-i;if (ans > tmp) ans = tmp;price[i] ++;}cout << ans << endl;}}


 


 

原创粉丝点击