太难的不会写,因为真的不会。。。
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
一个结构体存储每个武器及其四种属性值,第一个下标代表武器属性,第二个下标代表该种武器的第几个(<cnt[i])
struct war {
int a, b, c, d;
}item[55][55];
代码(AC)
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stdlib.h>
#include<vector>
#include<stack>
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
原题链接