zoj 1054 For the Porsche

该博客探讨了一种使用二进制状态表示客户需求的优化问题。在给定特征数量和客户要求的情况下,通过遍历所有可能的状态,寻找满足成本限制并最大化销售利润的特征组合。算法涉及位运算和动态规划,最终输出最优特征集和相关客户群体。
摘要由CSDN通过智能技术生成

这题利用了二进制表示状态

每个客户的需求可以表示为一个数字
例如
题目给出feature总数目为8个
然后某个客户要求要有 第1 、4、7个特征
那么这个客户的需求状态可以用二进制表示为
01001001
所以很显然,当feature总数为n个时
任意的需求状态 都可以用 0 到 (2^n)-1中的某个数字来表示
然后就是对所有的状态进行一个遍历,找出bestState ,再利用位运算进行输出

我也是看某大神的

#include<stdio.h>
#include<iostream>
#include<memory.h>
#include<string.h>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
using namespace std;

int max_cost, min_cost, f_num, c_num;
int f_cost[21], c_req[21][2], cus_satis[21], f_choose[21], cus_buy[21], bestState;
double PI;
int sales, total_cost, total_cus, profit_margin, total_feature;
int binV[21];

void inti() {
	PI = 0;
	sales = 0;
	total_cost = 0;
	total_cus = 0;
	profit_margin = 0;
	total_feature = 0;
}

int main() {
	int k = 1;
	for (int i = 0; i < 21; i++) {
		binV[i] = k;
		k *= 2;
	}
	int t, i, j, temp, state, coun;
	scanf("%d", &t);
	coun = 0;
	while (t--) {
		inti();
		scanf("%d%d%d%d", &min_cost, &max_cost, &f_num, &c_num);
		for (i = 0; i < f_num; i++) {
			scanf("%d", &f_cost[i]);
		}

		int total;
		for (i = 0; i < c_num; i++) {
			scanf("%d", &c_req[i][0]);
			total = 0;
			for (j = 0; j < c_req[i][0]; j++) {
				scanf("%d", &temp);
				total += binV[temp - 1];
			}
			c_req[i][1] = total;
			scanf("%d", &cus_buy[i]);
		}

		int curCost, curCus, curSales, curFeture;
		double curPI;

		for (state = 0; state < binV[f_num]; state++) {
			curCost = curCus = curSales = curFeture = 0;
			curPI = 0;
			for (i = 0; i < f_num; i++) {
				if (state & binV[i]) {
					curCost += f_cost[i];
					curFeture++;
				}
			}

			if (curCost < min_cost || curCost > max_cost)continue;

			for (i = 0; i < c_num; i++) {
				if ((state | c_req[i][1]) == state) {
					curSales += cus_buy[i];
					curCus++;
				}
			}


			curPI = curSales * 1.0 / curCost * 1.0;
			bool update = false;

			if (curPI > PI) {
				update = true;
			} else if (curPI == PI) {
				if (curSales - curCost > profit_margin) {
					update = true;
				} else if (curSales - curCost == profit_margin) {
					if (curFeture < total_feature) {
						update = true;
					} else if (curFeture == total_feature) {
						if (curCus > total_cus) {
							update = true;
						}
					}
				}
			}

			if (update) {
				PI = curPI;
				sales = curSales;
				total_cost = curCost;
				profit_margin = curSales - curCost;
				total_feature = curFeture;
				total_cus = curCus;
				bestState = state;
			}
		}

		printf("Feature Set %d\n", ++coun);
		printf("%.3f\n", PI);
		printf("%d\n", sales);
		printf("%d\n", total_cost);
		for (i = 0; i < f_num; i++) {
			if (bestState & binV[i]) {
				printf("%d", i + 1);
				i++;
				break;
			}
		}
		for (; i < f_num; i++) {
			if (bestState & binV[i]) {
				printf(" %d", i + 1);
			}
		}
		printf("\n");
		for (i = 0; i < c_num; i++) {
			if ((bestState | c_req[i][1]) == bestState) {
				printf("%d", i + 1);
				i++;
				break;
			}
		}
		for (; i < c_num; i++) {
			if ((bestState | c_req[i][1]) == bestState) {
				printf(" %d", i + 1);
			}
		}
		printf("\n");

	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值