洛谷-1092 虫食算

P1092 虫食算

Description

所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母。来看一个简单的例子:

http://paste.ubuntu.com/25448822/

其中#号代表被虫子啃掉的数字。根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5。

现在,我们对问题做两个限制:

首先,我们只考虑加法的虫食算。这里的加法是N进制加法,算式中三个数都有N位,允许有前导的0。

其次,虫子把所有的数都啃光了,我们只知道哪些数字是相同的,我们将相同的数字用相同的字母表示,不同的数字用不同的字母表示。如果这个算式是N进制的,我们就取英文字母表午的前N个大写字母来表示这个算式中的0到N-1这N个不同的数字:但是这N个字母并不一定顺序地代表0到N-1)。输入数据保证N个字母分别至少出现一次。

http://paste.ubuntu.com/25448824/

上面的算式是一个4进制的算式。很显然,我们只要让ABCD分别代表0123,便可以让这个式子成立了。你的任务是,对于给定的N进制加法算式,求出N个不同的字母分别代表的数字,使得该加法算式成立。输入数据保证有且仅有一组解

Put In

包含四行。第一行有一个正整数N(N<=26),后面的3行每行有一个由大写字母组成的字符串,分别代表两个加数以及和。这3个字符串左右两端都没有空格,从高位到低位,并且恰好有N位。

Put Out

包含一行。在这一行中,应当包含唯一的那组解。解是这样表示的:输出N个数字,分别表示A,B,C……所代表的数字,相邻的两个数字用一个空格隔开,不能有多余的空格。

Sample

输入样例#1:
5
ABCED
BDACE
EBBAA
输出样例#1:
1 0 3 4 2

Hints

对于30%的数据,保证有N<=10;

对于50%的数据,保证有N<=15;

对于全部的数据,保证有N<=26。

noip2004提高组第4题

 

Solution

听说正解是高斯消元呐,但是我不会~(>_<)~

看到大家都写了搜索。

一种实现很简单的方法是枚举1~n的排列,判断是否可行。我算了算时间复杂度(其实我不会算,就大概估计了一下),发现会超时。

由于不会算复杂度,我对于这样的暴搜能过50表示惊讶⊙ o ⊙ 

如果按照竖式从右至左的顺序搜,就可以边搜边判断是否可行了。

我写得很麻烦,讨论了很多情况,但是很多复制粘贴就可以了。

具体的:

用v[i]记录i所代表的值,use[i]记录是否有字母代表i这个数字。

搜索的时候,传入的参数有:当前到了哪一位,上一位是否进位。

然后搜到某一位的时候,判断哪些数被确定了,我分了0个,1个,2个,3个的情况,分别处理

(如果有多个没有确定,也只能枚举一个,然后进入下一个搜索,因为可能会出现,加数与加数或和的这一位是同一个字母的情况)

有一个剪枝是,搜到第i位的时候,判断一下第i位到第n位,有没有出现冲突的情况(冲突,即三个数都确定了,但是相加什么的并不符合条件)

还有比较神奇的优化,比如枚举的时候倒着枚举。

注意进位什么的。

 

经过和zcx的讨论后,我终于知道自己代码为什么这么长了。

学习了正常的方法。

搜索的时候,如果当前列有两个数不确定,就跳过这一列(就不用那么多分类讨论了)。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
using namespace std;
int n,a[31],b[31],c[31],v[31];
int use[31];
inline int read()
{
	register int ans=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)) {ans=ans*10+ch-'0';ch=getchar();}
	return ans*f;
}
int buf[5];
inline void write(int x)
{
    if (x<0) putchar('-'),x=-x;
    buf[0]=0;
    while (x) buf[++buf[0]]=x%10,x/=10;
    if (!buf[0]) buf[0]=1,buf[1]=0;
    while (buf[0]) putchar('0'+buf[buf[0]--]);
}
bool flag=0;
inline void init()
{
	for(register int j=1;j<=n;++j)
	{
		a[n-j+1]=getchar();
		while(a[n-j+1]<'A'||a[n-j+1]>'A'+n-1)
		  a[n-j+1]=getchar();
		a[n-j+1]-='A';
	}
	for(register int j=1;j<=n;++j)
	{
		b[n-j+1]=getchar();
		while(b[n-j+1]<'A'||b[n-j+1]>'A'+n-1)
		  b[n-j+1]=getchar();
		b[n-j+1]-='A';
	}
	for(register int j=1;j<=n;++j)
	{
		c[n-j+1]=getchar();
		while(c[n-j+1]<'A'||c[n-j+1]>'A'+n-1)
		  c[n-j+1]=getchar();
		c[n-j+1]-='A';
	}
}
void dfs(int now,int in)         //当前到哪一位,进位 
{
	int o;
	if(now==n+1)
	{
		flag=1;
		return;
	}
	for(int i=now;i<=n;i++)
	  if(v[a[i]]>-1&&v[b[i]]>-1&&v[c[i]]>-1)
	  {
	  	if((v[a[i]]+v[b[i]])%n==v[c[i]]||(v[a[i]]+v[b[i]]+1)%n==v[c[i]])
	  	  continue;
	  	else
	  	  return;
	  }
	if(v[a[now]]>-1&&v[b[now]]>-1&&v[c[now]]>-1)
	{
		if(v[a[now]]+v[b[now]]+in==v[c[now]]||(now!=n&&(v[a[now]]+v[b[now]]+in)%n==v[c[now]]))
		{
			dfs(now+1,(v[a[now]]+v[b[now]]+in)/n);
			if(flag)
			  return;
		}
		else
		  return;
	}
	if(v[a[now]]>-1&&v[b[now]]>-1&&v[c[now]]==-1)
	{
		if((v[a[now]]+v[b[now]]+in<n||now!=n)&&!use[(v[a[now]]+v[b[now]]+in)%n])
		{
			v[c[now]]=(v[a[now]]+v[b[now]]+in)%n;
			use[v[c[now]]]=1;
			dfs(now+1,(v[a[now]]+v[b[now]]+in)/n);
			if(flag)
			  return;
			use[v[c[now]]]=0;
			v[c[now]]=-1;
		}
		else
		  return;
	}
	if(v[a[now]]>-1&&v[b[now]]==-1&&v[c[now]]>-1)
	{
		if((v[c[now]]>v[a[now]]+in||now!=n)&&!use[(v[c[now]]-v[a[now]]-in+n)%n])
		{
			v[b[now]]=(v[c[now]]-v[a[now]]-in+n)%n;
			use[v[b[now]]]=1;
			dfs(now+1,(v[a[now]]+v[b[now]]+in)/n);
			if(flag)
			  return;
			use[v[b[now]]]=0;
			v[b[now]]=-1;
		}
		else
		  return;
	}
	if(v[b[now]]>-1&&v[a[now]]==-1&&v[c[now]]>-1)
	{
		if(v[c[now]]>v[b[now]]+in||now!=n)
		{
			v[a[now]]=(v[c[now]]-v[b[now]]-in+n)%n;
			use[v[a[now]]]=1;
			dfs(now+1,(v[b[now]]+v[a[now]]+in)/n);
			if(flag) return;
			use[v[a[now]]]=0;
			v[a[now]]=-1;
		}
		else
		  return;
	}
	if(v[a[now]]>-1&&v[b[now]]==-1&&v[c[now]]==-1)
	{
		o=n==now? n-v[a[now]]-in:n-in;
		for(register int i=o-1;i>=0;--i)
		if(!use[i])
		{
			v[b[now]]=i;use[i]=1;
			dfs(now,in);
			if(flag)
			  return;
			use[i]=0;v[b[now]]=-1;
		}
	}
	if(v[a[now]]==-1&&v[b[now]]>-1&&v[c[now]]==-1)
	{
		o=n==now? n-v[b[now]]-in:n-in;
		for(register int i=o-1;i>=0;--i)
		if(!use[i])
		{
			v[a[now]]=i;use[i]=1;
			dfs(now,in);
			if(flag)
			  return;
			use[i]=0;v[a[now]]=-1;
		}
	}
	if(v[a[now]]==-1&&v[b[now]]==-1&&v[c[now]]>-1)
	{
		o=n==now? v[c[now]]-in:n-1-in;
		for(register int i=o;i>=0;--i)
		if(!use[i])
		{
			v[a[now]]=i;use[i]=1;
			dfs(now,in);
			if(flag) return;
			v[a[now]]=-1;use[i]=0;
		}
	}
	if(v[a[now]]==-1&&v[b[now]]==-1&&v[c[now]]==-1)
	{
		o=n==now? n-in:n;
		for(register int i=o-1;i>=0;--i)
		if(!use[i])
		{
			v[a[now]]=i;use[i]=1;
			dfs(now,in);
			if(flag) return;
			v[a[now]]=-1;use[i]=0;
		}
	}
}
int main()
{
	n=read();
	init();
	for(register int i=0;i<n;++i)
	{
		use[i]=0;
		v[i]=-1;
	}
	dfs(1,0);
	for(register int i=0;i<n;++i)
	{
		write(v[i]);
		putchar(' ');
	}
	return 0;
}

 

posted @ 2017-09-28 14:47  o00v00o  阅读(513)  评论(0编辑  收藏  举报