zoukankan      html  css  js  c++  java
  • 洛谷-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;
    }
  • 相关阅读:
    图片和xml文件的转换
    WPF的样式(Style)继承
    .NET的序列化和反序列化
    WPF中的画板InkCanvas
    找到网页的源文件并找到歌曲文件的路径
    How to check if a ctrl + enter is pressed on a control?
    计算两个日期相差的天数
    图片保存到数据库以及从数据库中Load图片
    设计模式Command(命令模式)
    一个强大而且好用的UML设计工具
  • 原文地址:https://www.cnblogs.com/charlotte-o/p/7606649.html
Copyright © 2011-2022 走看看