这周没怎么做题,临近期末了也开始复习了,所以就没怎么做题,这一周还是主要的做的搜索。
简单地写一写题解吧。
洛谷题解 P1037 [NOIP2002 普及组] 产生数(佛洛依德+高精度)
1120 小木棍
链接:https://www.luogu.com.cn/problem/P1120
题意:
寻找一个最短的木头棍子能够把切成这个数组。
思路:
这个题吧,其实不仅仅是这个题,这个搜索吧,感觉最重要的是找dfs的变量代表的啥意思(真的是太难了,根本想不到)
这个题的主要的思路就是从数组里面的最大值开始遍历,直到遍历到sum/2中,从中找看看有没有能够符合题意的。符合题意得就直接结束循环。exit(0);
怎么根据一个棍的长度看他是否是符合题意的呢?
那么就需要用到dfs了这里面是最难想的,他的代码倒是不是很难理解,就是想不到他的变量。
需要四个变量:
表示这棵树多长、
表示剩下的最大长度、
表示还剩下几棵树、
表示已经拼凑的木棍长度。
剩下的就是对代码进行剪枝了。其实剪枝在写代码的时候就不由而来的就剪完了。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int num[59],maxn=0,minn=100,sum=0;
//need表示这棵树多长 // can表示剩下的最大长度
void dfs(int jike,int start,int need,int can){ //jike表示还剩下几棵树 //start表示已经拼凑的木棍长度
if(jike==0){
cout<<need<<endl;
exit(0);}
if(start==need)
{dfs(jike-1,0,need,maxn);return ;}
for(int i=can;i>=minn;i--){
if(num[i]&&i+start<=need) {
num[i]--;
dfs(jike,start+i,need,i);
num[i]++;
if(start==0||i+start==need)
return ;
}
}
}
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++) {
int x;cin>>x;
if(x<=50){
num[x]++;
maxn=max(maxn,x);
minn=min(minn,x);
sum+=x;}
}
for(int i=maxn;i<=sum/2;i++)
if(sum%i==0)dfs(sum/i,0,i,maxn);
cout<<sum<<endl; //如果一条也不对
}