POJ 1853 背包问题

Cat

Time Limit: 1500MS   Memory Limit: 30000K
Total Submissions: 1580   Accepted: 401   Special Judge

Description

In strong winds, sailboats tend to heel leeward (tilt away from the wind) like the one in the picture. Heeling is undesirable for at least two reasons. First, the effective sail area is reduced, as the effective height of the sail is multiplied by the cosine of the angle. Reduced sail area implies reduced speed. Second, the boat may heel to the point that its centre of gravity ceases to be above the hull, causing the boat to capsize.
To mitigate these problems, catamarans like the one shown split the
hull into two pieces (the port and starboard hulls). This design
increases the effective width of the boat. Increased width decreases the
vertical mechanical advantage of the sail, thus reducing heeling.
Increased width also increases the angle of heeling that can be
tolerated before the boat capsizes.

Heeling can also be mitigated by having the crew sit or stand on, or
even hike out beyond, the windward hull. If you look carefully at the
picture you can see the two person crew hiking to windward.

At some wind velocity, even these measures are insufficient to keep
the boat upright. A skipper‘s only choice (other than to capsize) is to
let out the sail, which reduces its effective horizontal dimension much
as heeling reduces its vertical dimension. As with heeling, this action
causes loss of speed. If the boat heels sufficiently, it may not even be
possible to let out the sail, as its outer corner may be obstructed by
the surface of the water!

Reefing is a mechanism for reducing the sail‘s area. Roller reefing
involves wrapping the sail around the boom (much like a window blind) so
as to reduce its height. With sufficient reefing, the heeling can be
controlled in almost any wind.

But reefing involves reduced speed, so our skipper has elected yet
another approach. She has decided to beach the boat and pick up some
rocks to use as ballast. Ballast is just dead weight added to hull,
which tends to counteract heeling. It slows the boat a bit (as it rides
lower in the water) but not nearly so much as reducing sail area.

Given n rocks, you are to compute how to divide them between the
port and starboard hulls so that the weight of rocks in each hull is
nearly equal.

Input

Input
contains several test cases. Each test case begins with 1 < n <=
100; the number of rocks to be added as ballast. Consider the rocks to
be numbered 1 through n. n lines follow; the ith line gives the weight
in kg of the ith rock - a positive real number not greater than 100. A
line containing 0 follows the last test case.

Output

For
each test case, output a single line giving the numbers of the rocks
that should be loaded as ballast into the starboard hull. Assume that
the other rocks will be loaded into the port hull. The total weight of
ballast in the port hull should not differ from that in the starboard
hull by more than 2%. If there are many solutions, any one will do.
There will always be a solution; indeed, there will always be a solution
that balances within 1%, but you aren‘t required to find it.

Sample Input

5
10.0
50.0
90.0
38.0
7.1
0

Sample Output

3 5

Source

Waterloo local 2004.09.19

题意:给定一定数量的物品和物品的质量,问是否能够把这些物品分成两堆,然后差别不差过2%;

解题思路:因为题目中涉及到了小数,所以不好用dp做,就需要把小数乘以一个数把它变成整数进行背包,在这个题中求出每一个物体的质量占总质量的比值然后乘以2000,再进行一次dp;

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cstdlib>
 6 #include<stack>
 7 using namespace std;
 8 const int maxn=22010;
 9 bool dp[maxn];
10 int n;
11 double input[107];
12 int num[107],road[maxn];
13 double sum;
14 stack<int> s;
15 void init()
16 {
17     memset(dp,0,sizeof(dp));
18     memset(num,0,sizeof(num));
19     sum=0;
20     while(!s.empty()) s.pop();
21 }
22 void DP()
23 {
24     dp[0]=1;
25     for(int i=1;i<=n;i++)
26     {
27         for(int j=10000;j>=0;j--)
28         {
29             if(dp[j]&&!dp[j+num[i]]) dp[j+num[i]]=1,road[j+num[i]]=i;
30
31         }
32     }
33 }
34 int main()
35 {
36  //   freopen("in.txt","r",stdin);
37     while(1){
38         scanf("%d",&n);
39         if(!n) break;
40         init();
41         double f;
42         for(int i=1;i<=n;i++) scanf("%lf",&input[i]),sum+=input[i];
43         for(int i=1;i<=n;i++) num[i]=input[i]/sum*20000;
47         DP();
48
49         int k;
50         for(int i=10000;i>=0;i--) if(dp[i]) {k=i;break;}
51
52         while(k>0){
53             s.push(road[k]);
54             k-=num[road[k]];
55         }
56         bool first=1;
57         while(!s.empty()){
58             if(first) printf("%d",s.top()),first=0;
59             else printf(" %d",s.top());
60             s.pop();
61         }
62         printf("\n");
63     }
64     return 0;
65 }
时间: 2024-10-20 10:18:28

POJ 1853 背包问题的相关文章

0-1背包问题,附上例题(POJ - 3624 Charm Bracelet)

0-1背包问题的题目样式 有 N 件物品和一个容量为 M 的背包.放入第 i 件物品耗费的费用是 Wi,得到的价值是 Vi.求解将哪些物品装入背包可使价值总和最大. 0-1背包问题关键在于该物品放或不放,即在当前容量为M的的情况下,选择不选择该物品,那么就有一个转移方程 for(i=0  -  N) for(j=0  -  M) dp[i][j] = max(dp[i-1][j],dp[i-1][j+w[i]]+v[i]); 当前物品为i,当前的背包容量为j,如果不选当前该物品,则选取dp[i-

POJ 1155 TELE 树形背包问题

题目描述看的莫名其妙,很久才看懂. 就是很裸的树形背包问题吧,状态是dp(i,j)表示节点i取到j个客户能得到的最大收益. 注意一开始初始化的时候所有j为0的时候应该是0,然后其他值都要初始化成负无穷,因为收益有可能是负值. 然后做01背包的时候注意方向,防止出现取某一个元素多次 #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <set&g

poj 1276 Cash Machine 背包问题

题目链接:http://poj.org/problem?id=1276 背包问题的动态规划 照着背包九讲打了个模板 此题特殊在重量和价值相等 而模板更具有一般性 在算f的过程中及时更新最大值 复杂度:V * Σ(log n[i]) 注意初始化 #include <cstdio> #include <cstdlib> #include <ctime> #include <iostream> #include <cmath> #include <

POJ 3132 Sum of Different Primes ( 满背包问题)

Sum of Different Primes Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 3280   Accepted: 2040 Description A positive integer may be expressed as a sum of different prime numbers (primes), in one way or another. Given two positive integer

poj 1742 Coins (动态规划,背包问题)

Coins Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 32977   Accepted: 11208 Description People in Silverland use coins.They have coins of value A1,A2,A3...An Silverland dollar.One day Tony opened his money-box and found there were some

POJ 3181 Dollar Dayz 01全然背包问题

01全然背包问题. 主要是求有多少种组合.二维dp做的人多了,这里使用一维dp就能够了. 一维的转换方程:dp[j] = dp[j-i] + dp[j];当中i代表重量,j代表当前背包容量. 意思就是dp[j-i] 代表j-i背包重量的时候最多的组合数,那么假设到了背包容量为j的时候,就是能够把第i个物品装进背包,那么就有dp[j-i]种装法, 假设没有i物品之前.那么容量为j的时候组合数是dp[j]. 那么当有i物品,且容量为j的时候,那么组合数就是dp[j-i] + dp[j]; 二维能够转

POJ 3181 Dollar Dayz 01完全背包问题

01完全背包问题. 主要是求有多少种组合.二维dp做的人多了,这里使用一维dp就可以了. 一维的转换方程:dp[j] = dp[j-i] + dp[j];其中i代表重量,j代表当前背包容量. 意思就是dp[j-i] 代表j-i背包重量的时候最多的组合数,那么如果到了背包容量为j的时候,就是可以把第i个物品装进背包,那么就有dp[j-i]种装法, 如果没有i物品之前,那么容量为j的时候组合数是dp[j]: 那么当有i物品,且容量为j的时候,那么组合数就是dp[j-i] + dp[j]; 二维可以转

POJ 3624 Charm Bracelet 背包问题的解决方案

最简单的背包问题,标题应该是除了背包测试中心:您无法打开二维数组.我还没有开的二维.光看数据是不可能的. 太大. 有两种方法来提高全省内存DP: 1 所谓卷的阵列 2 反向表 久没做背包DP,突然认为这样的背包问题非常easy了. 以下给出两种解法: 1 calBag()是滚动数组 2 calBag2()是逆向填表 #pragma once #include <stdio.h> #include <stdlib.h> #include <vector> using na

poj 1742 多重背包问题 dp算法

题意:硬币分别有 A1.....An种,每种各有C1......Cn个,问组成小于m的有多少种 思路:多重背包问题 dp[i][j]表示用前i种硬币组成j最多剩下多少个  dp=-1的表示凑不齐 dp[0][0]=0; for(int i=0;i<n;i++)     for(int j=0;j<=m;j++) {    if(dp[i][j]>=0)   dp[i+1][j]=c[i];  //表示用前i种可以凑齐j元,自然就全部剩下了       else if(j<a[i]|