宝石(暴力搜)

宝石

Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 0   Accepted Submission(s) : 0
Font: Times New Roman | Verdana | Georgia
Font Size:  

Problem Description

有一个商人喜欢收集一些宝石,有一天他得到了三种十分好看的宝石,把它们分别取名为 M, V, P。它们对应的单个价值为 DM, DV, DP。宝石可以两两合成,如M, V可以合成为新的高级宝石C, 价值为DC。 M, P 可以合成为新的高级宝石H,价值为DH。V, P 可以合成为新的高级宝石Y,价值为DY。最后,M, V, P 一起可以合成最高级宝石W, 价值为 DW。
现在,商人有一篮子宝石,以一个字符串表示。商人想知道如何合成这一篮子宝石,使得这一篮子的宝石价值和最大,每一个单个宝石最多只能合成一次或者不合成。求这一篮子的宝石的价值最大值。

Input

多组测试样例
每组测试样例第一行输入7个整数,分别表示DM, DV, DP, DC, DH, DY, DW。第二行输入一个字符串,如VVP, MVVPMMP等。所有整数的绝对值小于100。字符串长度小于等于40且不为空。 

Output

输出一个整数,表示这一篮子的宝石的最大价值。

Sample Input

1 1 1 2 2 2 5
PVM
-5 1 1 1 1 1 1
MMM

Sample Output

5
-15
#include<stdio.h>
int main(){
	int dm, dv, dp, dc, dh, dy, dw;
	int cc,ch,cy,cw;
	int fm,fv,fp;
	int i,max;
	int tm,tv,tp,t;
	char str[50];
	while(~scanf("%d%d%d%d%d%d%d",&dm,&dv,&dp,&dc,&dh,&dy,&dw)){
		scanf("%s",str);
		fm=fv=fp=i=0;
		while(str[i]){
			if(str[i]=='M')fm++;
			else if(str[i]=='V')fv++;
			else if(str[i]=='P')fp++;
			i++;
		}
		max=-200000000;
		for(cc=0;cc<=20;cc++){
			for(ch=0;ch<=20;ch++){
				for(cy=0;cy<=20;cy++){
					for(cw=0;cw<=20;cw++){
						tm=fm-cc-ch-cw;
						tv=fv-cc-cy-cw;
						tp=fp-ch-cy-cw;
						if(tm>=0&&tv>=0&&tp>=0){
							t=tm*dm+tv*dv+tp*dp;
							t+=cc*dc+ch*dh+cy*dy+cw*dw;
							if(max<t)max=t;
						}
					}
				}
			}
		}
		printf("%d\n",max);
	}
	
}

### 关于宝石组合问题的暴力解法 #### 问题描述 宝石组合问题是基于唯一分解定理设计的一道题目。该问题的核心在于通过因数分解的方式找到满足条件的所有可能组合。 #### 解决方案 为了实现暴力解法,可以采用如下方法: 1. **预处理素因子** 预先计算出给定范围内的所有质数及其幂次形式,以便后续快速查找符合条件的组合[^1]。 2. **枚举所有可能性** 使用嵌套循环逐一尝试每种可能的分配方式,并验证其是否符合题目中的约束条件。由于数据规模较小,在合理范围内可以直接穷尽所有情况而不用担心性能瓶颈[^3]。 以下是具体的代码实现: ```cpp #include <bits/stdc++.h> using namespace std; // 函数用于获取n的所有约数 vector<int> getDivisors(int n) { vector<int> divs; for (int i = 1; i * i <= n; ++i) { if (n % i == 0) { divs.push_back(i); if (i != n / i) divs.push_back(n / i); // 添加另一个除数 } } sort(divs.begin(), divs.end()); return divs; } int main() { int N, M; cin >> N >> M; // 输入宝石数量N以及总价值M // 获取每个宝石的价值数组A[] vector<int> A(N); for(auto &x : A){ cin>>x; } long long count=0; // 枚举子集并判断是否满足条件 for(int mask=0;mask<(1<<N);++mask){ long long product=1; bool valid=true; for(int j=0;j<N;++j){ if(mask&(1<<j)){ if(product>A[j]){ product=(product*A[j])%M; // 计算乘积并对M取模防止溢出 }else{ valid=false;break;// 如果当前值大于等于M则跳过此集合 } } } if(valid && product==M){ count++; } } cout << count; // 输出最终的结果数目 } ``` 上述程序片段展示了如何利用位掩码来遍历所有的子集组合,并检查这些子集中元素相乘后的结果是否正好匹配目标数值 \(M\) 。这里特别注意的是为了避免整型溢出采用了模运算技巧[^4]。 #### 结论 这种暴力解的方法虽然简单直观,但在实际应用时需考虑输入规模的影响。对于本题而言,得益于限定的数据大小,这种方法能够高效完成任务而不至于超出时间限制[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值