杭电多校——第二场(题解)

太难的不会写,因为真的不会。。。

1010 Lead of Wisdom

现在在题目单中已经可以找到6772Lead of Wisdom

题目大意

有t个测试案例
每个案例首先会有n,k,n代表接下来的n行会有n把武器,每个武器是不同的种类,并且均拥有a,b,c,d四种属性,k代表最多可以出现的武器种类最多有k种。
每种武器最多只能拿一把,也就是说当每一种武器都有的时候最多可以拿k把武器,如果有的武器种类没有就不能拿这种,所以武器数一定 <= k

需要求的值为在这里插入图片描述

分析

这题解法很暴力,就是把每一种情况的值都求出来然后依次比较找出最大值,不要担心超时,因为时间复杂度在这种情况下是n的k/n次方,最坏的时候就是
3的16(50/3)次方,并不算太大。

这句话我也没理解为什么会退化这么多,等我把搜索树看了再试图理解一下吧。。。
在这里插入图片描述
需要的工具:
cnt[k]:每一种类型的武器的数量
next[k]:每一种武器的下一种武器类型,主要是为了cnt[i] = 0的武器,存储为它的下一个不为零的武器类型,方便直接dfs
一个结构体存储每个武器及其四种属性值,第一个下标代表武器属性,第二个下标代表该种武器的第几个( struct war {
int a, b, c, d;
}item[55][55];

代码(AC)

#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int MAX_N = 55;

int n, k;
long long ans;
int cnt[MAX_N];
int nxt[MAX_N];

struct war {
    int a, b, c, d;
}item[MAX_N][MAX_N];

void solve(int x,int a,int b,int c,int d) {
    if(x > k) {
    	//终止条件,到了最后一个属性,计算并比较更新ans 
    	long long temp = (long long)a * b * c * d;
    	if(temp > ans) ans = temp;
    	return;
	}
	
	if(!cnt[x]) {
		solve(nxt[x],a,b,c,d);
		return;
	}
	for(int i = 1; i <= cnt[x] ; i ++) {
		solve(x + 1 , a + item[x][i].a , b + item[x][i].b , c + item[x][i].c ,  d + item[x][i].d );
	}
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
    int T;
    cin >> T;
    while (T--) {
    	ans = 0;//每次重新计算清零答案 
    	memset(cnt,0,sizeof(cnt));
        cin >> n >> k;
        int x;
        while(n--) {
        	cin >> x;
        	cnt[x]++;
        	cin>>item[x][cnt[x]].a>>item[x][cnt[x]].b>>item[x][cnt[x]].c>>item[x][cnt[x]].d;
		}
		//处理next数组
		x = k + 1;
		for(int i = k; i ; i--) {
			nxt[i] = x;
			if(cnt[i])
				x = i;
		}
        solve(1,100,100,100,100);
        cout<<ans<<endl;
    }
    return 0;
}

有个很莫名其妙的点,在放了这些头文件之后用next数组会报编译错误,改成nxt就ac了,好像是某个stl迭代器头文件里有一个next的同名方法,所以具体是哪一个我也不知道。

1001 Total Eclipse

原题链接

你可能感兴趣的:(题解)