57pts,有注释,求调,玄关
查看原帖
57pts,有注释,求调,玄关
1059176
Quartz_Blocks楼主2024/7/16 22:45
#include <bits/stdc++.h>
using namespace std;
int n,a[70],tot,mx = -1,m;
int x = 0;
bool vis[70];
bool flag = 0;
void dfs(int sum,int count,int last){
	if(flag) return;
	if(count == tot/x-1){//递归边界,只需要搜索到当前最多的木棒数量(tot/x)再减去1即可。减去1是因为如果其它的都已经知道,那么这个也就可以知道。
		flag = 1;
		return;
	}
	for(int i = last+1;i <= n;i++){//last排列变组合,见Line52
		if(vis[i]) continue;//如果当前要使用的木棒已经被使用
		vis[i] = 1;//标记木棒,使得下次不会被重复使用
		if(a[i] + sum == x){//刚好凑出来一根木棒,进入下一根,此时last要归0
			dfs(0,count+1,0);
		}else if(a[i] + sum < x){//否则继续凑木棒,下一次只需要从 i 开始搜索即可
			dfs(a[i]+sum,count,i);
		}
		//如果 a[i]+sum > x ,则不会进入下一层的递归,不会产生任何的影响
		vis[i] = 0;//回溯分支,与上面的成对。见Line61
		if(flag == 0 && sum == 0) return;//可行性剪枝1
		if(flag == 0 && sum+a[i] == x) return;//可行性剪枝2
	}
}
bool cmp(int x,int y){return x>y;}//排序规则,因为必须从大到小排序,否则没有意义
int main(){
	cin >> m;//m作为临时变量
	for(int i = 1;i <= m;i++){
		int k;
		cin >> k;
		if(k <= 50){//过滤不合法的值
			a[++n] = k,mx = max(k,mx);//a[++n]被赋值,mx取最大值
			tot += k;//求总和
		}
	}
	sort(a+1,a+1+n,cmp);//排序使得最优
	for(int i = mx;i <= tot;i++){//此处是从mx到tot
		//不用清零vis数组,上一次遗留的值已经被回溯清零,不会产生影响
		if(tot % i == 0){//只有是tot的因数才有可能成为最终的答案
			x = i;//给dfs函数存储的i值,如果递归时每一层都存储将会浪费大量的空间
			dfs(1,0,0);//开始递归,初始选择第1根木棒填充,已经填充0个单位长度,从第0个开始
			if(flag == 1){//出现正解,为最小的答案
				cout << i;//输出
				return 0;//程序结束
			}
			flag = 0;//否则要将这里归0
		}
	}
	return 0;//不可能用到的结束条件
	
}
2024/7/16 22:45
加载中...