搜索技术——《算法竞赛入门到进阶》

迭代加深搜索

具体的操作方法:

  1. 先设定搜索深度为1,用DFS搜索到第一层即停止。也就是说,用DFS搜索一个深度为1的搜索树。
  2. 如果没有找到答案,再设定深度为2,用DFS搜索到第二层即停止。也就是说,用DFS搜索一个深度为2的搜索树。
  3. 继续设定深度为3,4……逐步扩大DFS的搜索深度,直到找到答案。
    这个迭代过程,在每一层的广度上采用了BFS的思想,在具体编程实现上则是DFS的。

题目 埃及分数
将一个分数 a/b,分解成若干个单位分数1/x的和,要求找到加数个数最少且最小的单位分数最大的方案。

#include 
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 
#include 
#include 
#include 
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;
}

你可能感兴趣的:(算法,数据结构)