ZOJ - 2575 Full of Painting

Description

Tingting wants to draw and stucco N squares with N different colors full of the base line of a wall.

Give you the number of squares, the length of the wall, the minimum size and the maximal size of each square and the price of stuccoing one centiare of the wall with a special color. Your task is to calculate the minimum cost.

Input

For each case, the first line is two integers, N, L(1 <= N <= 5, 1 <= L <= 200), N is the number of squares that tingting wants to draw, L is the total length of the wall. The second line is N positive floating numbers, the I-th number of this line means the price of stuccoing one centiare of the wall with I-th color. Then N lines follow, Each line contains two integers, MinI, MaxI(1 <= MinI <= MaxI <= L), which indicates the size of I-th square. For simplify, you can assume that all the sizes of squares are integers. Certainly you should also realize that you can paint each square with the color you like, but each color can only be used once.

Output

Output the minimum cost, one line percase, if he can't draw the requirement squares, just output "Impossible".

Sample Input

2 5
1.0 2.0
1 5
1 5
2 5
1.0 2.0
3 4
3 4

Sample Output

17.000
Impossible

题意:给定n个限定了边长范围的正方形,现在要把它们全部铺到长度固定,高度不限的墙上,一共有N种颜色,告诉每种颜色的单位面积价格。问铺满墙的最少开销是多少?只要长度为L的墙被覆盖了所有长度即可。

思路:DP,设f[i][j][k]表示到第i个长度为j颜色选k时的最小开销,其中k表示状态,每次枚举到第i个的时候,状态k1表示的颜色的个数一定要是i-1个,这样才能转移

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 205;
const int inf = 0x3f3f3f3f;

int n, k;
int bit[50], L[10], H[10];
double f[205][50];
double pri[10];

int get(int x) {
	int cnt = 0;
	for (int i = 0; i < 5; i++) 
		if (x & (1<<i))
			cnt++;
	return cnt;
}

void init() {
	for (int i = 0; i < 40; i++)
		bit[i] = get(i);
}

void solve() {
	for (int i = 0; i <= k; i++)	
		for (int j = 0; j <= 31; j++)
			f[i][j] = inf;

	f[0][0] = 0;
	for (int i = 1; i <= n; i++) {
		for (int j = k; j >= L[i]; j--) {
			for (int p = L[i]; p <= j && p <= H[i]; p++) {
				for (int l = 0; l <= 31; l++)  {
					if (bit[l] != i-1 || f[j-p][l] == inf) 
						continue;
					for (int h = 0; h < n; h++)
						if (!(l & (1 << h)))
							f[j][l|(1<<h)] = min(f[j][l|(1<<h)], f[j-p][l] + p*p*pri[h+1]);
				}
			}
		}
	}

	if (f[k][(1<<n)-1] == inf)
		printf("Impossible\n");
	else printf("%.3lf\n", f[k][(1<<n)-1]);
}

int main() {
	init();
	while (scanf("%d%d", &n, &k) != EOF) {
		for (int i = 1; i <= n; i++)
			scanf("%lf", &pri[i]);

		for (int i = 1; i <= n; i++)
			scanf("%d%d", &L[i], &H[i]);

		solve();
	}
	return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值