题目大意是每组给定n个装备,每个装备属于一个类别,并有四个属性a,b,c,d。每个类别仅允许挑选一个装备最终伤害值为所有选定装备的四个属性分别与100求和再相乘。问最大值为多少
看完题目,满脑子都是暴力搜索,一看数据规模,n <= 50。
推算一下搜索的复杂度,最坏情况是装备均分到每个组,则有如下复杂度分析:
于是美美的交了第一发暴力:
#include
#include
#define N 55
using namespace std;
int item[N][N];
int t,n,K;
int a[N];
int b[N];
int c[N];
int d[N];
long long ans;
void dfs(int k,int sumA,int sumB,int sumC,int sumD){
if(k > K){
long long temp = 1LL * sumA * sumB * sumC * sumD;
ans = ans > temp ? ans : temp;
return;
}
if(item[k][0] == 0){
dfs(k + 1,sumA,sumB,sumC,sumD);
return;
}
for(int i = 1;i <= item[k][0];i++){
dfs(k + 1,sumA + a[item[k][i]],sumB + b[item[k][i]],sumC + c[item[k][i]],sumD + d[item[k][i]]);
}
}
int main(){
for(cin >> t;t;t--){
ans = 0;
scanf("%d%d",&n,&K);
for(int i = 1;i <= K;i++){
item[i][0] = 0;
}
for(int i = 1,ki;i <= n;i++){
scanf("%d",&ki);
item[ki][++item[ki][0]] = i;
scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
}
dfs(1,100,100,100,100);
printf("%lld\n",ans);
}
}
于是妥妥的tle,淦。
仔细思考发现,对于没有装备的组来说,单单在搜索时到下一层是不合适的,每次枚举都会遍历这些层,所以最终的复杂度就变成了O(n3n/3)。
上面的4 * 107 再乘上 n = 50 那就是 50 * 4 * 107 = 2 * 109那可是要超时。。。。。。
所以对于没有装备的分组来说,应该直接跳过,而不是让它走下一层。这个预处理一个nxt数组
指向下一个非零的组编号即可:
ac代码
#include
#include
#define N 55
using namespace std;
int item[N][N];
int cnt[N];
int t,n,K;
int a[N];
int b[N];
int c[N];
int d[N];
int nxt[N];
long long ans;
void dfs(int k,int sumA,int sumB,int sumC,int sumD){
if(k > K){
long long temp = 1LL * sumA * sumB * sumC * sumD;
ans = ans > temp ? ans : temp;
return;
}
if(cnt[k] == 0){
dfs(nxt[k],sumA,sumB,sumC,sumD);
return;
}
for(int i = 1;i <= cnt[k];i++){
dfs(k + 1,sumA + a[item[k][i]],sumB + b[item[k][i]],sumC + c[item[k][i]],sumD + d[item[k][i]]);
}
}
int main(){
scanf("%d",&t);
while(t--){
ans = 0;
scanf("%d%d",&n,&K);
for(int i = 1;i <= K;i++){
cnt[i] = 0;
}
for(int i = 1,ki;i <= n;i++){
scanf("%d",&ki);
item[ki][++cnt[ki]] = i;
scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
}
for(int i = K,nx = K + 1;i >= 1;i--){
nxt[i] = nx;
if(cnt[i]) nx = i;
}
dfs(1,100,100,100,100);
printf("%lld\n",ans);
}
}