HDOJ 6772 Lead of Wisdom (dfs) (杭电多校2020第二场1010) 题解

http://acm.hdu.edu.cn/showproblem.php?pid=6772
题意:给n个装备,分别具有abcd四个属性
装备一共有k种类型,每个类型只能选一个。

D M G = ( 100 + ∑ i ∈ S a i ) ( 100 + ∑ i ∈ S b i ) ( 100 + ∑ i ∈ S c i ) ( 100 + ∑ i ∈ S d i ) DMG=(100+∑i∈Sai)(100+∑i∈Sbi)(100+∑i∈Sci)(100+∑i∈Sdi) DMG=(100+iSai)(100+iSbi)(100+iSci)(100+iSdi)
的最大值
思路:
暴搜。可能遇到一个类型的装备数量为0的情况,遇到这种情况,会使树多一层,要跳过这种情况浪费的时间,可以通过维护nxt[MAXN]数组,来跳过那些数量为0的类型。

Claris大佬如是说:"需要注意的是,cnt i = 0 (在我的程序里面是c[i]=0) 的部分应该直接跳过,以保证搜索树上每一层的节点数至少是上 一层的两倍,使得时间复杂度为 O(3n/3 ),否则会退化成 O(n3n/3 ) 而 TLE。"*

#include
#include
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repb(i,a,b) for(int i=(a);i>=(b);i--)
const int MAXN = 53;

struct Item{
	int a,b,c,d;
}it[MAXN][MAXN];

int n,k;
int aa,bb,cc,dd;
int nxt[MAXN],c[MAXN];
long long res;

void dfs(int pos){
	if(pos>k){
		res = max(res,1ll*aa*bb*cc*dd);
		return;
	}
	for(int i=1;i<=c[pos];i++){
		aa += it[pos][i].a;bb += it[pos][i].b;
		cc += it[pos][i].c;dd += it[pos][i].d;
		dfs(nxt[pos]);
		aa -= it[pos][i].a;bb -= it[pos][i].b;
		cc -= it[pos][i].c;dd -= it[pos][i].d;
	}
	if(!c[pos]) dfs(nxt[pos]); 
}

void solve(){
	cin>>n>>k;
	int typ;
	rep(i,1,k) c[i] = 0;
	rep(i,1,n){
		scanf("%d",&typ);
		c[typ]++;
		scanf("%d%d%d%d",&it[typ][c[typ]].a,&it[typ][c[typ]].b,&it[typ][c[typ]].c,&it[typ][c[typ]].d);
	} 
	int tt = k+1;
	repb(i,k,1){
	//这个nxt是关键,因为如果不能直接跳过c[i]=0的点会慢很多 
		nxt[i] = tt;
		if(c[i]) tt = i;
	}
	aa = bb = cc = dd = 100;
	res = 100000000; 
	dfs(1);
	printf("%lld\n",res);
}

int main(){
	/*
	freopen("1010in.txt","r",stdin);
	freopen("outputs.txt","w",stdout);
	*/
	int z;
	cin>>z;
	while(z--) solve();
}

你可能感兴趣的:(DFS,杭电多校)