zoukankan      html  css  js  c++  java
  • POJ 3093 Margaritas(Kind of wine) on the River Walk (背包方案统计)

    题目

    Description

    One of the more popular activities in San Antonio is to enjoy margaritas in the park along the river know as the River Walk. Margaritas may be purchased at many establishments along the River Walk from fancy hotels toJoe’s Taco and Margarita stand. (The problem is not to find out how Joe got a liquor license. That involves Texas politics and thus is much too difficult for an ACM contest problem.) The prices of the margaritas vary depending on the amount and quality of the ingredients and the ambience of the establishment. You have allocated a certain amount of money to sampling different margaritas.

    Given the price of a single margarita (including applicable taxes and gratuities) at each of the various establishments and the amount allocated to sampling the margaritas, find out how many different maximal combinations, choosing at most one margarita from each establishment, you can purchase. A valid combination must have a total price no more than the allocated amount and the unused amount (allocated amount – total price) must be less than the price of any establishment that was not selected. (Otherwise you could add that establishment to the combination.)

    For example, suppose you have $25 to spend and the prices (whole dollar amounts) are:

    Vendor A B C D H J
    Price 8 9 8 7 16 5

    Then possible combinations (with their prices) are:

    ABC(25), ABD(24), ABJ(22), ACD(23), ACJ(21), ADJ( 20), AH(24), BCD(24), BCJ(22), BDJ(21), BH(25), CDJ(20), CH(24), DH(23) and HJ(21).

    Thus the total number of combinations is 15.

    Input

    The input begins with a line containing an integer value specifying the number of datasets that follow, N (1 ≤ N ≤ 1000). Each dataset starts with a line containing two integer values V and D representing the number of vendors (1 ≤ V ≤ 30) and the dollar amount to spend (1 ≤ D ≤ 1000) respectively. The two values will be separated by one or more spaces. The remainder of each dataset consists of one or more lines, each containing one or more integer values representing the cost of a margarita for each vendor. There will be a total of V cost values specified. The cost of a margarita is always at least one (1). Input values will be chosen so the result will fit in a 32 bit unsigned integer.

    Output

    For each problem instance, the output will be a single line containing the dataset number, followed by a single space and then the number of combinations for that problem instance.

    Sample Input

    2
    6 25
    8 9 8 7 16 5
    30 250
    1 2 3 4 5 6 7 8 9 10 11
    12 13 14 15 16 17 18 19 20
    21 22 23 24 25 26 27 28 29 30

    Sample Output

    1 15
    2 16509438

    Hint

    Note: Some solution methods for this problem may be exponential in the number of vendors. For these methods, the time limit may be exceeded on problem instances with a large number of vendors such as the second example below.

    思路

    1. 朴素背包方案统计的状态转移方程为 dp[i] += dp[i-w[i]]

    2. 题目要求背包剩下的空间无法再放下任意一个还未被选择的物品, 那么需要特殊考虑

    • 先对所有物品按照其价值进行排序, 对于每件物品都有拿或者不拿两种选择
    • 对于第 k 件物品, 分拿或不拿两种选择. 假设第 k 件物品是未拿到的价值最小的, 那么 0~k-1 这 k 件物品一定都拿了. 然后对 K+1 ~ END 执行朴素背包方案统计即可

    3. 下面的代码解析.

    • delta 是指 0 ~ K-1 这 K 件物品的价值总和, 每次循环加上 dp[i], 因此名为 delta
    • 初始化 dp[delta] = 0, dp[else] = 0

    代码: 

    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 1010;
    int testCase, V, D;
    int w[MAXN];
    int dp[MAXN];
    int solve_dp() {
    	int solution = 0;
    	int delta = 0;
    	for(int i = 0; i < V; i ++) {
    		
    		memset(dp, 0, sizeof(dp));
    		dp[delta] = 1;
    		for(int j = i+1; j < V; j++) {
    			for(int k = D; k >= delta+w[j]; k--) {
    				dp[k] = dp[k]+dp[k-w[j]];
    			}
    		}
    
    		for(int k = D; k > max(0, D-w[i]); k --) { // WA 过一次, 写成 >=, 等于的话就可以装下 i 了
    			if(k >= delta) {
    				solution += dp[k];
    			}
    		}
    		delta += w[i];
    	}
    	return solution;
    }
    
    int main() {
    		freopen("E:\Copy\ACM\测试用例\in.txt", "r", stdin);
    
    	cin >> testCase;
    	int index = 0;
    	while(testCase--) {
    		index++;
    		cin >> V >> D;
    		for(int i = 0; i < V; i ++) {
    			scanf("%d", &w[i]);
    		}
    		sort(w, w+V);//WA 过, 忘了排序
    		// mainFunc
    		printf("%d %d
    ", index, solve_dp());
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    个人应该做什么样的网站?
    得对xls文件作操作
    正则替换
    31 反馈的判断方法(2)
    AD 层次原理图设计 自上而下
    27 多级放大电路的频率响应与第四章集成运放的电流源电路
    P28 集成运放的电流源电路(2)
    32 负反馈放大电路的方块图
    ESP8266固件AT指令连接EMQ 的MQTT服务器
    33 深度负反馈的实质与放大倍数分析
  • 原文地址:https://www.cnblogs.com/xinsheng/p/3456396.html
Copyright © 2011-2022 走看看