2020 HDU多校 第二场 10-Lead of Wisdom(dfs + 剪枝)

题目链接: 10-Lead of Wisdom

Description

题意:给n把武器,每种武器只能选一件,每件武器有四个属性值,更具属性值之和的乘积计算伤害值,选出伤害值最大的武器搭配

In an online game, “Lead of Wisdom” is a place where the lucky player can randomly get powerful items.

There are k types of items, a player can wear at most one item for each type. For the i-th item, it has four attributes ai,bi,ci and di. Assume the set of items that the player wearing is S, the damage rate of the player DMG can be calculated by the formula:

DMG=(100+∑i∈S ai)(100+∑i∈S bi)(100+∑i∈S ci)(100+∑i∈S di)

Little Q has got n items from “Lead of Wisdom”, please write a program to help him select which items to wear such that the value of DMG is maximized.

Input

  • The first line of the input contains a single integer T (1 ≤ T ≤ 10), the number of test cases.
  • For each case, the first line of the input contains two integers n and k (1 ≤ n, k ≤ 50), denoting the number of items and the number of item types.
  • Each of the following n lines contains five integers ti,ai,bi,ci and di (1 ≤ ti ≤ k, 0 ≤ ai, bi, ci, di ≤ 100), denoting an item of type ti whose attributes are ai,bi,ci and di.

Output

For each test case, output a single line containing an integer, the maximum value of DMG.

Sample Input

1
6 4
1 17 25 10 0
2 0 0 25 14
4 17 0 21 0
1 5 22 0 10
2 0 16 20 0
4 37 0 0 0

Sample Output

297882000

Method

  • 看到n, k <= 50 就知道可以用暴搜了
  • 但是wa了一发之后发现没有武器的那种武器在搜索过程中会过度消耗时间
  • 所以应该跳过这类武器,方法可以用数组来记录下一把武器种类,也可以用map做一个离散化
  • 但是这个题目把我恶心吐了,因为max()函数和if条件选择的不同,前者就TLE,后者就A了,真是为难本蒟蒻了

Code

详见注释

#include 
#include 

using namespace std;
#define Max 55
#define ll long long

int T, n, k, a[Max][Max][5], num[Max], adv[Max];	//a数组存第i种武器的第j把的第k属性值、num数组存武器数量、adv数组存下一把武器的种类(间接离散化) 
ll ans = 0;

void dfs(int x, int e, int b, int c, int d)			//dfs+剪枝 
{
	if(x == k+1) {
		ll temp = (ll)e*b*c*d;
		if(ans < temp) ans = temp;					//用max就TLE了,用if就A了,这你敢信?给本蒟蒻整吐了 
		//ans = max(ans, (ll)e*b*c*d);
		return ;
	}
	if(!num[x]) {									//剪枝,如果当前武器没有,则直接dfs下一把有数量的武器 
		dfs(adv[x], e, b, c, d);
	}
	else 
	 	for(int i=0; i<num[x]; i++)					//正常dfs 
		{
			dfs(x+1, e+a[x][i][1], b+a[x][i][2], c+a[x][i][3], d+a[x][i][4]);
		}
	return ;
}

int main()
{
	scanf("%d", &T);
	while(T--)
	{
		ans = 0;
		int t;
		scanf("%d%d", &n, &k);
		for(int i=1; i<=k; i++) num[i] = 0;			//记得初始化num数组 
		for(int i=0; i<n; i++)
		{
			scanf("%d", &t);
			for(int j=1; j<=4; j++)
			{
				scanf("%d", &a[t][num[t]][j]);
			}
			num[t]++;
		}
		t = k+1;
		for(int i=k; i>0; i--)						//生成adv数组,从后往前遍历num数组即可 
		{
			adv[i] = t;
			if(num[i]) t = i;
		}
		dfs(1, 100, 100, 100, 100);
		printf("%lld\n", ans);
	}
	return 0;
}

蒟蒻一只,欢迎指正

你可能感兴趣的:(训练赛病历,搜索)