蓝桥杯-防御力

1.题目描述

小明最近在玩一款游戏。对游戏中的防御力很感兴趣。
我们认为直接影响防御的参数为“防御性能”,记作d,而面板上有两个防御值A和B,与d成对数关系,A=2d,B=3dA=2 注意任何时候上式都成立)。
在游戏过程中,可能有一些道具把防御值A增加一个值,有另一些道具把防御值B增加一个值。现在小明身上有n1个道具增加A的值和n2个道具增加B的值,增加量已知。
现在已知第i次使用的道具是增加A还是增加B的值,但具体使用那个道具是不确定的,请找到一个字典序最小的使用道具的方式,使得最终的防御性能最大。
初始时防御性能为0,即d=0,所以A=B=1。

输入

输入的第一行包含两个数n1,n2,空格分隔。
第二行n1个数,表示增加A值的那些道具的增加量。
第三行n2个数,表示增加B值的那些道具的增加量。
第四行一个长度为n1+n2的字符串,由0和1组成,表示道具的使用顺序。0表示使用增加A值的道具,1表示使用增加B值的道具。输入数据保证恰好有n1个0,n2个1。

输出

对于每组数据,输出n1+n2+1行,前n1+n2行按顺序输出道具的使用情况,若使用增加A值的道具,输出Ax,x为道具在该类道具中的编号(从1开始)。若使用增加B值的道具则输出Bx。最后一行输出一个大写字母E。

样例输入

1 2
4
2 8
101

样例输出

B2
A1
B1
E

2.题解

2.1 贪心算法

思路

这里的贪心证明使用数学证明并不好证,但我们可以先确定可能的贪心策略,并带入具体数据进行测试,选出最优解(做题技巧)
一共有四种贪心策略:
1.A道具效果从小到大使用,B道具效果从小到大使用
2.A道具效果从小到大使用,B道具效果从大到小使用
3.A道具效果从大到小使用,B道具效果从大到小使用
4.A道具效果从大到小使用,B道具效果从小到大使用

检测:

好的,为了证明策略2(即 A 道具效果从小到大使用,B 道具效果从大到小使用)是最优的,让我们选择一个具体的例子,并进行详细计算和比较。

示例

假设输入数据如下:

  • ( n1 = 2 ), ( n2 = 2 )
  • 增加 ( A ) 值的道具增加量:[4, 6]
  • 增加 ( B ) 值的道具增加量:[8, 3]
  • 使用顺序:[0, 1, 0, 1]

四种贪心策略:

策略1:A 道具效果从小到大使用,B 道具效果从小到大使用

  • A 道具:[4, 6]
  • B 道具:[3, 8]

使用顺序:[0, 1, 0, 1]

  1. 使用 A 道具4
    • ( A=1+4=5)
    • ( d=log2(5)2.322 )
    • ( B=32.32210.6 )
  2. 使用 B 道具3
    • ( $B = 10.6 + 3 = 13.6 )
    • ( d=log3(13.6)2.311)
    • ( A=22.3114.92 )
  3. 使用 A 道具6
    • ( $A = 4.92 + 6 = 10.92 )
    • ( d=log2(10.92)3.457 )
    • ( B=33.45740.95 )
  4. 使用 B 道具8
    • ( B=40.95+8=48.95)
    • ( d=log3(48.95)3.663)
    • ( A=23.66312.9)

最终防御性能 ( d3.663)。

策略2:A 道具效果从小到大使用,B 道具效果从大到小使用

  • A 道具:[4, 6]
  • B 道具:[8, 3]

使用顺序:[0, 1, 0, 1]

  1. 使用 A 道具4
    • ( A=1+4=5)
    • ( d=log2(5)2.322 )
    • ( B=32.32210.6 )
  2. 使用 B 道具8
    • ( B=10.6+8=18.6)
    • ( d=log3(18.6)2.715 )
    • ( A=22.7156.55 )
  3. 使用 A 道具6
    • ( A=6.55+6=12.55 )
    • ( d=log2(12.55)3.647 )
    • ( B=33.64753.1 )
  4. 使用 B 道具3
    • ( B=53.1+3=56.1)
    • ( d=log3(56.1)3.828 )
    • ( A=23.82814.5 )

最终防御性能 ( d3.828)。

策略3:A 道具效果从大到小使用,B 道具效果从大到小使用

  • A 道具:[6, 4]
  • B 道具:[8, 3]

使用顺序:[0, 1, 0, 1]

  1. 使用 A 道具6
    • ( A=1+6=7 )
    • ( d=log2(7)2.807 )
    • ( B=32.80718.5 )
  2. 使用 B 道具8
    • ( B=18.5+8=26.5 )
    • ( $$d = \log_3(26.5) \approx 3.008$ )
    • ( A=23.0088.03 )
  3. 使用 A 道具4
    • ( A=8.03+4=12.03 )
    • ( d=log2(12.03)3.584 )
    • ( B=33.58449.9 )
  4. 使用 B 道具3
    • ( B=49.9+3=52.9 )
    • ( d=log3(52.9)3.775 )
    • ( A=23.77513.9 )

最终防御性能 ( d3.775 )。

策略4:A 道具效果从大到小使用, B 道具效果从小到大使用

  • A 道具:[6, 4]
  • B 道具:[3, 8]

使用顺序:[0, 1, 0, 1]

  1. 使用 A 道具6
    • ( A=1+6=7)
    • ( d=log2(7)2.807 )
    • ( B=32.80718.5 )
  2. 使用 B 道具3
    • ( B=18.5+3=21.5 )$
    • ( d=log3(21.5)2.924 )
    • ( A=22.9247.56 )
  3. 使用 A 道具4
    • ( A=7.56+4=11.56 )
    • ( d=log2(11.56)3.529 )
    • ( B=33.52947.9 )
  4. 使用 B 道具8
    • ( B=47.9+8=55.9 )
    • ( d=log3(55.9)3.825 )
    • ( A=23.82514.48 )

最终防御性能 ( d \approx 3.825 )。

结论

通过比较不同策略的最终防御性能 (d):

  • 策略1:( d3.663 )
  • 策略2:( d3.828)
  • 策略3:( d3.775 )
  • 策略4:( d3.825 )

可以看出,策略2(A道具效果从小到大使用,B道具效果从大到小使用)得到了最高的最终防御性能 ( d3.828 )。

因此,策略2在这个例子中确实是最优的。

然后我们很容易发现使用第2种策略是最优的,大概数学证明如下:

我们可以发现A和B增大同样的大小,d=log2(A),d=log3(B), A对于d的影响更大,提升速度更快,由于增大量x是固定的,但是每次对d的影响实际上取决于 x/A, 我们希望每次增量都使这种提升最大,充分利用每一次增量,就要求每次使用这个x之前,之前积累的和A越小越好,也就是A增量从小到大,但同时B的增大也会通过影响d反过来影响A的增大,我们希望尽量减小A的增大,也就是令x/B越小越好,让B从大到小即可。

代码

#include<bits/stdc++.h>
using namespace std;
bool compare1(pair<int,int> p1, pair<int, int> p2){
	if(p1.second != p2.second)
		return p1.second < p2.second;
	return p1.first <= p2.first;
}

bool compare2(pair<int,int> p1, pair<int, int> p2){
	if(p1.second != p2.second)
		return p1.second > p2.second;
	return p1.first <= p2.first;
}
int main(){
	int n1, n2;
	cin >> n1 >> n2;
	
	vector<pair<int,int>> items1(n1), items2(n2);
	for(int i = 0; i < n1; i++){
		items1[i].first = i + 1;
		cin >> items1[i].second;
	}
	for(int i = 0; i < n2; i++){
		items2[i].first = i + 1;
		cin >> items2[i].second;
	}
	string op;
	cin >> op;
	
	sort(items1.begin(), items1.end(),compare1);
	sort(items2.begin(), items2.end(), compare2);
	int cnt1 = 0, cnt2 = 0;
	for(char ch : op){
		if(ch == '0'){
			printf("A%d\n",items1[cnt1++].first);
		} else{
			printf("B%d\n",items2[cnt2++].first);
		}
	}
	printf("E");
	return 0;
} 
posted @   DawnTraveler  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示