01背包问题*3
2017-09-02 20:11
323 查看
HDU2546 饭卡
Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 22098 Accepted Submission(s): 7730
Problem Description
电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额。如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够)。所以大家都希望尽量使卡上的余额最少。
某天,食堂中有n种菜出售,每种菜可购买一次。已知每种菜的价格以及卡上的余额,问最少可使卡上的余额为多少。
Input
多组数据。对于每组数据:
第一行为正整数n,表示菜的数量。n<=1000。
第二行包括n个正整数,表示每种菜的价格。价格不超过50。
第三行包括一个正整数m,表示卡上的余额。m<=1000。
n=0表示数据结束。
Output
对于每组输入,输出一行,包含一个整数,表示卡上可能的最小余额。
Sample Input
1
50
5
10
1 2 3 2 1 1 2 3 2 1
50
0
Sample Output
-45
32
【分析】要使余额最少,最划算的方法当然是用最后的5元买一个最贵的菜。因此先把这5元留出来,对n-1种菜,m-5元余额做一下01背包,将剩下的钱减去最贵的菜即可。
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> using namespace std; #define maxn 1005 int N,V; int w[maxn]; int dp[maxn]; int main(){ while(scanf("%d",&N)==1&&N){ for(int i=0;i<N;i++){ scanf("%d",&w[i]); } scanf("%d",&V); memset(dp,0,sizeof(dp)); sort(w,w+N); if(V<5){ printf("%d\n",V); continue; } for(int i=0;i<N-1;i++){ for(int j=V-5;j>=w[i];j--){ dp[j]=max(dp[j],dp[j-w[i]]+w[i]); } } printf("%d\n",V-dp[V-5]-w[N-1]); } return 0; }
HDU2955 Robberies
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 20096 Accepted Submission(s): 7443
Problem Description
The aspiring Roy the Robber has seen a lot of American movies, and knows that the bad guys usually gets caught in the end, often because they become too greedy. He has decided to work in the lucrative business of bank robbery only for a short while, before
retiring to a comfortable job at a university.
For a few months now, Roy has been assessing the security of various banks and the amount of cash they hold. He wants to make a calculated risk, and grab as much money as possible.
His mother, Ola, has decided upon a tolerable probability of getting caught. She feels that he is safe enough if the banks he robs together give a probability less than this.
Input
The first line of input gives T, the number of cases. For each scenario, the first line of input gives a floating point number P, the probability Roy needs to be below, and an integer N, the number of banks he has plans for. Then follow N lines, where line
j gives an integer Mj and a floating point number Pj .
Bank j contains Mj millions, and the probability of getting caught from robbing it is Pj .
Output
For each test case, output a line with the maximum number of millions he can expect to get while the probability of getting caught is less than the limit set.
Notes and Constraints
0 < T <= 100
0.0 <= P <= 1.0
0 < N <= 100
0 < Mj <= 100
0.0 <= Pj <= 1.0
A bank goes bankrupt if it is robbed, and you may assume that all probabilities are independent as the police have very low funds.
Sample Input
3
0.04 3
1 0.02
2 0.03
3 0.05
0.06 3
2 0.03
2 0.03
3 0.05
0.10 3
1 0.03
2 0.02
3 0.05
Sample Output
2
4
6
【题意】抢劫银行j可获得金额Mj,被抓的概率是Pj。当被抓概率小于P时,强盗是安全的。问在安全的前提下,抢匪最多能获得多少钱。
【分析】看上去是一个背包容量为P的裸01背包,但要注意这里的Pi是小数,并且题目没有限定精确到第几位(想直接乘100的梦想破灭了),因此需要转化一下,把金额当做“容量”来做。我的做法是求出:获得每一个金额需要付出的最小被抓概率,状态转移方程为:dp[j]=min(dp[j],dp[j-c[i]]+p[i]-dp[j-c[i]]*p[i]);然后从最大金额往下找概率小于P的即可。这题另外一个重要的地方是,这里的概率不是直接相加的关系,抢银行x和y后的被抓概率是x+y-x*y。(此题提示我们所有01背包其实都可以换种思路做)
#include<cstdio> #include<iostream> #include<algorithm> #in d53e clude<cstring> using namespace std; #define maxn 105 float P,p[maxn],dp[maxn*maxn]; int N,c[maxn],sum; int main(){ int T; scanf("%d",&T); while(T--){ scanf("%f%d",&P,&N); sum=0; for(int i=1;i<=N;i++){ scanf("%d%f",&c[i],&p[i]); sum+=c[i]; } for(int i=1;i<=sum;i++){ dp[i]=1.0; } dp[0]=0; sum=0; for(int i=1;i<=N;i++){ sum+=c[i]; for(int j=sum;j>=c[i];j--){ float x=dp[j-c[i]]; dp[j]=min(dp[j],x+p[i]-x*p[i]); } } for(int i=sum;i>=0;i--){ if(dp[i]<P){ printf("%d\n",i); break; } } } return 0; }
HDU1171 Big Event in HDU
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 35145 Accepted Submission(s): 12188
Problem Description
Nowadays, we all know that Computer College is the biggest department in HDU. But, maybe you don't know that Computer College had ever been split into Computer College and Software College in 2002.
The splitting is absolutely a big event in HDU! At the same time, it is a trouble thing too. All facilities must go halves. First, all facilities are assessed, and two facilities are thought to be same if they have the same value. It is assumed that there is
N (0<N<1000) kinds of facilities (different value, different kinds).
Input
Input contains multiple test cases. Each test case starts with a number N (0 < N <= 50 -- the total number of different facilities). The next N lines contain an integer V (0<V<=50 --value of facility) and an integer M (0<M<=100 --corresponding number of the
facilities) each. You can assume that all V are different.
A test case starting with a negative integer terminates input and this test case is not to be processed.
Output
For each case, print one line containing two integers A and B which denote the value of Computer College and Software College will get respectively. A and B should be as equal as possible. At the same time, you should guarantee that A is not less than B.
Sample Input
2
10 1
20 1
3
10 1
20 2
30 1
-1
Sample Output
20 10
40 40
【题意】有n种设备,每种设备有m台,每台价值为v。要求将这些设备分为价值最为接近的两组,A组价值需要不比B组低。
【分析】求一下价值的总和然后除以2,这就是B组价值的上限。以这个值为容量做一下01背包,然后用总价值减去求得的价值获得A组价值。要注意的是输入的价值数据是每种一个数据的,要处理成每台一个数据才能做。
【……】其实算一下复杂度的话,达到10^9,纯01背包能过还是很人品的,看了下discuss都说数据弱了,据说正解是:1.母函数,2.多重背包(01背包 + 二进制优化)。然后还有人dfs0ms过了。
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> using namespace std; #define maxn 55 #define maxm 105 int dp[maxn*maxn*maxm],m[maxn],v[maxn],val[maxn*maxm],sum,s; int main(){ int N,k; while(scanf("%d",&N)&&N>0){ sum=0; k=1; for(int i=1;i<=N;i++){ scanf("%d%d",&v[i],&m[i]); sum+=v[i]*m[i]; for(int j=1;j<=m[i];j++){ val[k]=v[i]; k++; } } s=sum/2; memset(dp,0,sizeof(dp)); for(int i=1;i<k;i++){ for(int j=s;j>=val[i];j--){ dp[j]=max(dp[j],dp[j-val[i]]+val[i]); } } printf("%d %d\n",sum-dp[s],dp[s]); } return 0; }
相关文章推荐
- 动态规划 4、基础背包问题总结(从01开始)
- 背包问题(01背包,完全背包,多重背包)
- 01背包问题的求解
- hdu 2602 背包问题之01背包
- 01背包问题
- 01背包问题
- 01背包问题
- 背包问题---01背包
- 背包问题---01背包最优方案总数(原理剖析代码实现)
- 01 背包问题
- 01背包问题——饭卡
- 01背包问题C
- 背包问题中的01背包和完全背包
- 01背包--苹果,背包问题
- 01背包问题的动态规划算法、蛮力法和空间优化算法
- 01背包问题和完全背包问题
- 01背包采药问题 模版
- 01背包问题和完全背包问题
- 01背包问题:poj 3624 Charm Bracelet
- 01背包问题和完全背包问题