迭代加深搜索
具体的操作方法:
- 先设定搜索深度为1,用DFS搜索到第一层即停止。也就是说,用DFS搜索一个深度为1的搜索树。
- 如果没有找到答案,再设定深度为2,用DFS搜索到第二层即停止。也就是说,用DFS搜索一个深度为2的搜索树。
- 继续设定深度为3,4……逐步扩大DFS的搜索深度,直到找到答案。
这个迭代过程,在每一层的广度上采用了BFS的思想,在具体编程实现上则是DFS的。
题目 埃及分数
将一个分数 a/b,分解成若干个单位分数1/x的和,要求找到加数个数最少且最小的单位分数最大的方案。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int ans[105],vis[105],maxed;
ll gcd(ll a,ll b)//求a和b的公约数
{
return b?gcd(b,a%b):a;
}
ll get_first(ll a, ll b)
{//确定一个分母,1/c是最贴近并小于a/b的
ll c=b/a;
if(b%a)
c++;
return c;
}
bool better(int d)
{
for(int i=d;i>=1;i--)
{
if(vis[i]!=ans[i])
{
return ans[i]==0||vis[i]<ans[i];
}
}
return false;
}
bool dfs(int step,int c,ll a,ll b)
{//step代表dfs搜索的第几层
if(step==maxed)
{
if(b%a)
return false;
vis[step]=b/a;//得到分母并标记好
if(better(step))
{//保证加数不重复
memcpy(ans,vis,sizeof(vis));
}
return true;
}
c=max((ll)c,get_first(a,b));
bool sign=false;
for(int i=c;;i++)
{
if(b*(maxed-step+1)<=i*a)
break;
vis[step]=i;//存分母
ll b2=b*i;//a2和b2是减去此时得到的分数1/i后得到的新的分子和分母
ll a2=a*i-b;
ll k=gcd(a2,b2);//得到公约数
if(dfs(step+1,i+1,a2/k,b2/k))
sign=true;
}
return sign;
}
int main()
{
ll a,b;
scanf("%lld%lld",&a,&b);//a是分子,b是分母
for(maxed=1;;maxed++)
{
if(dfs(1,get_first(a,b),a,b))
{
break;
}
}
printf("%lld/%lld=1/%d",a,b,ans[1]);
for(int i=2;i<=maxed;i++)
printf("+1/%d",ans[i]);
return 0;
}
题目 DNA sequence
The twenty-first century is a biology-technology developing century. We know that a gene is made of DNA. The nucleotide bases from which DNA is built are A(adenine), C(cytosine), G(guanine), and T(thymine). Finding the longest common subsequence between DNA/Protein sequences is one of the basic problems in modern computational molecular biology. But this problem is a little different. Given several DNA sequences, you are asked to make a shortest sequence from them so that each of the given sequence is the subsequence of it.
For example, given “ACGT”,“ATGC”,“CGTT” and “CAGT”, you can make a sequence in the following way. It is the shortest but may be not the only one.
Input
The first line is the test case number t. Then t test cases follow. In each case, the first line is an integer n ( 1<=n<=8 ) represents number of the DNA sequences. The following k lines contain the k sequences, one per line. Assuming that the length of any sequence is between 1 and 5.
Output
For each test case, print a line containing the length of the shortest sequence that can be made from these sequences.
Sample Input
1
4
ACGT
ATGC
CGTT
CAGT
Sample Output
8
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;
int T,n,vis[10],sizee;//sizee为构造的DNA的最短长度,vis[i]表示第i个序列正在占用的位置
char c[10]="ACTG";
struct node{
char s[10];
int len;
};
node a[10];
int length()//还需要几个位置
{
int ans=0;
for(int i=0;i<n;i++)
{
ans=max(ans,a[i].len-vis[i]);
}
return ans;
}
int dfs(int b)//b代表当前长度
{
if(b+length()>sizee)
return 0;
if(length()==0)
return 1;
int pos[10];
for(int i=0;i<4;i++)
{
int sign=0;
for(int j=0;j<n;j++)
pos[j]=vis[j];
for(int j=0;j<n;j++)
{
if(a[j].s[vis[j]]==c[i])
{
sign=1;
vis[j]++;
}
}
if(sign)
{
if(dfs(b+1))
{
return 1;
}
for(int j=0;j<n;j++)//否则
{
vis[j]=pos[j];
}
}
}
return 0;
}
int main()
{
scanf("%d",&T);
while(T--){
sizee=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
cin>>a[i].s;
a[i].len=strlen(a[i].s);
sizee=max(sizee,a[i].len);
vis[i]=0;
}
while(1)
{
if(dfs(0))
break;
sizee++;
}
cout<<sizee<<endl;
}
return 0;
}