[ NAIPC2016 ] C. Greetings! [状压DP + 枚举子集]

版权声明:将来的你一定会感谢现在努力的你!!!! https://blog.csdn.net/qq_37383726/article/details/82930473

题目链接
Your greeting card company makes unique greeting cards. The sizes of these greeting cards vary widely because of the whims of card designers. There are a lot of different types of cards, and each has a specific quantity that you need to manufacture.

Your job is to determine what envelopes to order for these greeting cards. You have a strict limit on the different number of different sizes of envelopes, which may be less than the number of distinct sizes of cards. You need to have envelopes so that every card fits in some envelope, possibly with room to spare, and the amount of waste paper is minimized. Measure the waste paper by the area of the envelope that is in excess of the area of the card, for each card. For example, a 10 \times 410×4 card in a 10 \times 410×4 envelope has no wasted paper, but a 10 \times 410×4 card in a 12 \times 512×5 envelope has waste of 2020. You may not rotate the cards to fit them in the envelopes better.

Suppose that you have 55 types of cards: 10 \times 1010×10 (55 of these), 9 \times 89×8 (1010 of these), 4 \times 124×12 (2020 of these), 12 \times 412×4 (88 of these), and 2 \times 32×3 (1616 of these).

Now, suppose that you can only buy one type of envelope. Since all cards have to fit in that one envelope size, the smallest envelope size you can use is 12 \times 1212×12, with an area of 144144. The wastes by each type of card are 144-10\cdot10 = 44144−10⋅10=44, 144-9\cdot8 = 72144−9⋅8=72, 144-4\cdot12 = 96144−4⋅12=96, 144-12\cdot4 = 96144−12⋅4=96, and 144-2\cdot3 = 138144−2⋅3=138, respectively. The total waste is 44\cdot5+72\cdot10+96\cdot20+96\cdot8+138\cdot16 = 583644⋅5+72⋅10+96⋅20+96⋅8+138⋅16=5836.

Suppose that you can buy 22 types of envelopes. The best you can do is to put the 10 \times 1010×10, 9 \times 89×8 and 12 \times 412×4 cards in 12 \times 1012×10 envelopes, and the 4 \times 124×12 and 2 \times 32×3 cards in 4 \times 124×12 envelopes. That adds up to waste of 18281828.

If you can buy 55 types of envelopes, then you can match one envelope type to each card type, and there’s no waste!

Given a list of card types and the number of types of envelopes you can buy, what is the smallest amount of wasted paper you can achieve?

Input
Each input will consist of a single test case. Note that your program may be run multiple times on different inputs. The first line of the input will consist of two space-separated integers nn and kk (1 \le n, k \le 15)(1≤n,k≤15), where nn is the number of different types of cards, and kk is the maximum number of types of envelopes you can order. Each of the following nn lines will consist of three integers, describing a type of card. The integers are ww, hh and qq (1 \le w, h, q \le 10,000)(1≤w,h,q≤10,000), where ww is the width of the cards of this type, hh is the height of the cards, and qq is the quantity of cards of this type.

Output
Output a single integer, representing the smallest possible total amount of wasted paper.

样例输入
5 1
10 10 5
9 8 10
4 12 20
12 4 8
2 3 16
样例输出
5836
样例输入
5 2
10 10 5
9 8 10
4 12 20
12 4 8
2 3 16
样例输出
1828
样例输入
5 5
10 10 5
9 8 10
4 12 20
12 4 8
2 3 16
样例输出
0
题目来源
The North American Invitational Programming Contest 2016

分析: d p [ I ] [ S ] dp[I][S] 表示: 最多用 I I 个信封装 S S 的最小浪费.
那么 d p [ I ] [ S ] = m a x ( d p [ I ] [ S ] , d p [ I 1 ] [ s u b ] + d p [ 1 ] [ S s u b ] ) , s u b S dp[I][S] = max(dp[I][S], dp[I - 1][sub] + dp[1][S - sub]), sub \subseteq S
Code

 
#include <bits/stdc++.h>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <string>
#include <math.h>
#include <stack>
#include <vector>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define rep(i, l, r) for(int i = l; i < r; i++)
#define per(i, r, l) for(int i = r; i >= l; i--)
#define dbg(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<<"\n"


typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int>pii;

const int N = (int) 16;
const int M = (int) 1e6 + 11;
const int MOD = (int) 1e9 + 7;
const int INF = (int) 0x3f3f3f3f;
const ll INFF = (ll) 0x3f3f3f3f3f3f3f3f;
/*-----------------------------------------------------------*/
void test(){
	int S = 10;
	int sub = S;
	do{
		string s = "";
		int t = sub;
		while(t){
			s += t % 2 + '0';
			t /= 2;
		}
		reverse(s.begin(), s.end());
		cout << s <<"\n";

		sub = (sub - 1) & S;
	}while(sub != S);
}

int w[N], h[N], q[N];
ll dp[N][1 << N];
int main(){
	//test();
	int n, k; 
	while(~scanf("%d%d", &n, &k)) {
		rep(i, 0, n) scanf("%d%d%d", w + i, h + i, q + i);
		memset(dp[0], 0, sizeof(dp[0]));
		rep(i, 0, 1 << n){
			ll mxw = 0, mxh = 0;		
			rep(j, 0, n){
				if(i >> j & 1) {
					mxw = max(mxw, (ll)w[j]);
					mxh = max(mxh, (ll)h[j]);
				}
			}
			rep(j, 0, n){
				if(i >> j & 1){
					dp[0][i] += q[j] * 1ll * (mxw * mxh - w[j] * h[j]);
				}
			}
		}

		rep(I, 1, k){
			rep(S, 0, 1 << n){
				int sub = S;
				dp[I][S] = dp[I - 1][S];
				do{
					dp[I][S] = min(dp[I][S], dp[I - 1][sub] + dp[0][S - sub]);
					sub = (sub - 1) & S;
				}while(sub != S);
				//			dbg(dp[I][S]);
			}
		}
		printf("%lld\n", dp[k - 1][(1 << n) - 1]);
	}	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37383726/article/details/82930473