[NOIP2004提高组]虫食算

题目:洛谷P1092、codevs1064、Vijos P1099。

题目大意:
给你一个$n$进制、每个数都是$n$位的三个数a,b,c,这些数的数位由字母表示(共$n$个字母,从‘A’开始),所有数字都只对应一个字母,每个字母对应一个数字。
现在知道a+b=c,求每个字母代表的数字,保证有且仅有一组解。
解题思路:
暴力,从后往前搜索每一列即可。注意传递进位。
若一列知道了三个数,则判断是否合法,合法则继续搜索下一列。
若一列知道了两个数,则可以推算出第三个数,若没被使用,则继续搜索下一列。
若一列知道的数少于一个,则a或b中,一定有一个数字是不知道的。我们从大到小枚举那个数的值,然后搜**当前列**(递归)。
如果发现答案可行,则直接输出答案,退出即可。
这样搜,不用加其他剪枝,最大一个点最多800ms(其实上述分类讨论已经很好地进行了剪枝)。

C++ Code:

#include<bits/stdc++.h>
int n,num[123],ur[123];
char a[123],b[132],c[213];
void dfs(int now,int jw){
	if(now==-1){
		for(int i=1;i<n;++i)printf("%d ",num[i+‘A‘-1]);
		printf("%d\n",num[n+‘A‘-1]);
		exit(EXIT_SUCCESS);
	}
	int i=now;
	//if(now!=n-1&&!check(now+1))return;
	if(num[a[i]]!=-1&&num[b[i]]!=-1&&num[c[i]]!=-1){
		int p=num[a[i]]+num[b[i]]+jw;
		if(p%n==num[c[i]]){
			dfs(now-1,p/n);
		}
		return;
	}
	if(num[a[i]]!=-1&&num[b[i]]!=-1){
		int p=num[a[i]]+num[b[i]]+jw;
		if(!ur[p%n]){
			ur[p%n]=1;
			num[c[i]]=p%n;
			dfs(now-1,p/n);
			num[c[i]]=-1;
			ur[p%n]=0;
		}
		return;
	}
	if(num[a[i]]!=-1&&num[c[i]]!=-1){
		int p=num[c[i]]-jw-num[a[i]]+n;
		if(!ur[p%n]){
			ur[p%n]=1;
			num[b[i]]=p%n;
			dfs(now-1,!(p/n));
			num[b[i]]=-1;
			ur[p%n]=0;
		}
		return;
	}
	if(num[b[i]]!=-1&&num[c[i]]!=-1){
		int p=num[c[i]]-jw-num[b[i]]+n;
		if(!ur[p%n]){
			ur[p%n]=1;
			num[a[i]]=p%n;
			dfs(now-1,!(p/n));
			num[a[i]]=-1;
			ur[p%n]=0;
		}
		return;
	}
	if(num[a[i]]!=-1){
		for(int j=n-1;j>-1;--j)
		if(!ur[j]){
			ur[j]=1;
			num[b[i]]=j;
			dfs(now,jw);
			num[b[i]]=-1;
			ur[j]=0;
		}
	}else{
		for(int j=n-1;j>-1;--j)
		if(!ur[j]){
			ur[j]=1;
			num[a[i]]=j;
			dfs(now,jw);
			num[a[i]]=-1;
			ur[j]=0;
		}
	}
}
int main(){
	scanf("%d%s%s%s",&n,a,b,c);
	memset(ur,0,sizeof ur);
	memset(num,-1,sizeof num);
	dfs(n-1,0);
	return EXIT_FAILURE;
}

原文地址:https://www.cnblogs.com/Mrsrz/p/9026478.html

时间: 2024-11-02 17:21:34

[NOIP2004提高组]虫食算的相关文章

[NOIP2004] 提高组 洛谷P1092 虫食算

题目描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045 +8468#6633 44445509678 其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5. 现在,我们对问题做两个限制: 首先,我们只考虑加法的虫食算.这里的加法是N进制加法,算式中三个数都有N位,允许有前导的0. 其次,虫子把所有的数都啃光了,我们只知道哪些数字是相同的,我们将相同的数字用

CODEVS1064虫食算noip提高组T4

题目描述 Description 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045    +    8468#6633       44445506978 其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5. 现在,我们对问题做两个限制: 首先,我们只考虑加法的虫食算.这里的加法是N进制加法,算式中三个数都有N位,允许有前导的0. 其次,虫子把所有的数都啃光

69. [NOIP2004] 虫食算

69. [NOIP2004] 虫食算 ★★★   输入文件:alpha.in   输出文件:alpha.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045    + 8468#6633 ----------- 44445509678 其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是

NOIP2004 虫食算

四.虫食算 (alpha.pas/dpr/c/cpp) [问题描述] 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045     +    8468#6633        44445506978 其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5. 现在,我们对问题做两个限制: 首先,我们只考虑加法的虫食算.这里的加法是N进制加法,算式中三个数都有N位,允许

【NOIP2004】虫食算

Description 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045 +   8468#6633 44445509678 其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5. 现在,我们对问题做两个限制: 首先,我们只考虑加法的虫食算.这里的加法是N进制加法,算式中三个数都有N位,允许有前导的0. 其次,虫子把所有的数都啃光了,我们只知道哪些数字是相同的

[NOIP2004]虫食算 T4 简单搜索+剪枝

最近在刷搜索套餐 我先做了一道简单的 虫食算.... 我GO die了........... 这都是啥啊!!!!!!!!!!!!!!! 总之就是一个搜啊.... 从最右面开始搜 每一行行尾进行check 基本上能过9个点........ 剪枝的话 ,考虑检索前面的每一行 如果改行的数字都己经试过,那么就可以判断合法性,如果已经有两个试过的话,考虑第三个数是否可能(可能已经被用过) 注意:试数的时候从后向前试...坑爹的数据 注意进位即可 下面是代码,调试信息懒得删....搜索的第四层可删 略长.

noip2004提高组题解

这次有两道题以前已经做过了,所以分数什么的也没有意义了.发现这年的难度设置极不靠谱,前三题都比较简单,最后一题太难,不知道出题人怎么想的. 第一题:储蓄计划 模拟. 第二题:合并果子 贪心.每次选最小的两堆合并. 第三题:合唱队形 两次动规.题目可以转化为找出一个人,使得以他为尾的最长上升子序列的长度最大,并且以他为首的最长下降子序列的长度也最大. 第四题:虫食算 马上想到搜索.但是规模太大,N可能有26位,如果简单枚举那么运算次数是26!≍4e27:剪枝方面只想到一个很弱的剪枝(对于26的规模

洛谷—— P1092 虫食算

https://www.luogu.org/problem/show?pid=1092 题目描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: http://paste.ubuntu.com/25448822/ 其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5. 现在,我们对问题做两个限制: 首先,我们只考虑加法的虫食算.这里的加法是N进制加法,算式中三个数都有N位,允许有前

虫食算

题目描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045 +8468#6633 44445509678 其中#号代表被虫子啃掉的数字.根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5. 现在,我们对问题做两个限制: 首先,我们只考虑加法的虫食算.这里的加法是N进制加法,算式中三个数都有N位,允许有前导的0. 其次,虫子把所有的数都啃光了,我们只知道哪些数字是相同的,我们将相同的数字用