HNU11374:GREAT+SWERC=PORTO(DFS)

Problem description

We want to have a great SWERC at Porto this year and we approached this challenge in several ways. We even framed it as a word addition problem, similar to the classic SEND+MORE=MONEY, where each letter stands for a single digit (0, 1, 2, ..., 8, 9) that
makes the arithmetic operation correct. In word additions different letters cannot be assigned the same digit and the leftmost letter in a word cannot be zero (0). In particular, a single letter term cannot be zero.

Given a word addition problem, compute the number of solutions (possibly zero).

Input

A line with an integer n, followed by n lines containing a word each with maximum length of 10 letters. The first n-1 words are the terms to be added and the last line is the result.

Words contain only capital letters. If words have different lengths, they must be interpreted as aligning to the right. For instance, in the SEND+MORE=MONEY problem, the D of the first word and E of the second word align with the Y of the final word. You can
also assume that the size of the last word is greater than or equal to the maximum size of the preceding words, and moreover, at most ten distinct letters are involved in a word problem.

3<=n<=10 Each word has at most 10 symbols (capital letters). A word problem has at most 10 distinct letters.

Output

A single line with an integer: the number of solutions of the word addition problem given as input.

Sample Input
3
GREAT
SWERC
PORTO
3
SEND
MORE
MONEY
5
TOO
GOOD
TO
BE
TRUE
Sample Output
6
1
93
Problem Source
HNU Contest 

题意:

给出你一个字母组成的加法式子,在右对齐之后,前n-1个相加得到第n个字符串,要求你对每个字母赋值0~9,每个字母代表的数字不能一样,且没有前导0,有几种赋值方法

思路:

直接对于每个字母分别尝试不同的赋值,搜索下去

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <math.h>
#include <bitset>
#include <algorithm>
#include <climits>
using namespace std;

#define ls 2*i
#define rs 2*i+1
#define UP(i,x,y) for(i=x;i<=y;i++)
#define DOWN(i,x,y) for(i=x;i>=y;i--)
#define MEM(a,x) memset(a,x,sizeof(a))
#define W(a) while(a)
#define gcd(a,b) __gcd(a,b)
#define LL long long
#define N 20005
#define INF 0x3f3f3f3f
#define EXP 1e-8
#define rank rank1
const int mod = 1000000007;

int n,letter[20],cot,len[20],hsh[200],num[200],ans;
char str[20][20];

int check()
{
    int i,j,k;
    for(i = 0; i<n; i++)//前导0不行
    {
        if(num[str[i][0]]==0)
            return 0;
    }
    int jin = 0;//进位
    for(j = 0; j<len[n-1]; j++)//从右边(个位)开始算
    {
        if(num[str[n-1][len[n-1]-1-j]]==-1) return 1;//这个字母没有被赋值,返回并往下搜
        int sum = jin;
        for(i = 0; i<n-1; i++)
        {
            if(len[i]-1-j<0) continue;
            if(num[str[i][len[i]-1-j]]==-1) return 1;//这个字母没有被赋值,返回并往下搜
            sum+=num[str[i][len[i]-1-j]];
        }
        if(sum%10!=num[str[n-1][len[n-1]-1-j]]) return 0;//对应位之和与最后一个不等
        jin=sum/10;
    }
    return !jin;//进位为0则解决了
}

void dfs(int cnt)
{
    int i;
    if(cnt==-1)
    {
        ans++;
        return;
    }
    for(i = 0; i<10; i++)//给字母尝试所有不同的赋值赋值
    {
        if(hsh[i]==0)
        {
            hsh[i] = 1;
            num[letter[cnt]] = i;
            if(check())//赋值可行则继续进行
                dfs(cnt-1);
            hsh[i] = 0;
            num[letter[cnt]] = -1;
        }
    }
}

int main()
{
    int i,j,k;
    while(~scanf("%d",&n))
    {
        MEM(hsh,0);
        cot = -1;
        for(i = 0; i<n; i++)
        {
            scanf("%s",str[i]);
            len[i] = strlen(str[i]);
            for(j = 0; j<len[i]; j++)
            {
                if(!hsh[str[i][j]])
                {
                    hsh[str[i][j]] = 1;
                    letter[++cot] = str[i][j];//记录所有字母
                }
            }
        }
        ans = 0;
        MEM(hsh,0);
        MEM(num,-1);
        dfs(cot);
        printf("%d\n",ans);
    }

    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-09 04:53:29

HNU11374:GREAT+SWERC=PORTO(DFS)的相关文章

UVALive 6884 GREAT + SWERC = PORTO dfs模拟

题目连接: https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4896 We want to have a great SWERC at Porto this year and we approached this challenge in several ways.We even framed it as a word add

HNU13377:Book Club(DFS)

Problem description Porto's book club is buzzing with excitement for the annual book exchange event! Every year, members bring their favorite book and try to find another book they like that is owned by someone willing to trade with them. I have been

解救小哈——DFS算法举例

一.问题引入 有一天,小哈一个人去玩迷宫.但是方向感不好的小哈很快就迷路了.小哼得知后便去解救无助的小哈.此时的小哼已经弄清楚了迷宫的地图,现在小哼要以最快的速度去解救小哈.那么,问题来了... 二.问题的分析 首先我们用一个二维数组来存储这个迷宫,刚开始的时候,小哼处于迷宫的入口处(1,1),小哈在(p,q).其实这道题的的本质就在于找从(1,1)到(p,q)的最短路径. 此时摆在小哼面前的路有两条,我们可以先让小哼往右边走,直到走不通的时候再回到这里,再去尝试另外一个方向. 在这里我们规定一

【BZOJ4942】[Noi2017]整数 线段树+DFS(卡过)

[BZOJ4942][Noi2017]整数 题目描述去uoj 题解:如果只有加法,那么直接暴力即可...(因为1的数量最多nlogn个) 先考虑加法,比较显然的做法就是将A二进制分解成log位,然后依次更新这log位,如果最高位依然有进位,那么找到最高位后面的第一个0,将中间的所有1变成0,那个0变成1.这个显然要用到线段树,但是复杂度是nlog2n的,肯定过不去. 于是我在考场上yy了一下,这log位是连续的,我们每次都要花费log的时间去修改一个岂不是很浪费?我们可以先在线段树上找到这段区间

uva1103(dfs)

UVA - 1103 还是没写好,,看的别人的 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <cstring> 5 #include <algorithm> 6 #include <cstdlib> 7 #include <stack> 8 #include <cctype> 9 #include <str

poj 1088 滑雪 DP(dfs的记忆化搜索)

题目地址:http://poj.org/problem?id=1088 题目大意:给你一个m*n的矩阵 如果其中一个点高于另一个点 那么就可以从高点向下滑 直到没有可以下滑的时候 就得到一条下滑路径 求最大的下滑路径 分析:因为只能从高峰滑到低峰,无后效性,所以每个点都可以找到自己的最长下滑距离(只与自己高度有关).记忆每个点的最长下滑距离,当有另一个点的下滑路径遇到这个点的时候,直接加上这个点的最长下滑距离. dp递推式是,dp[x][y] = max(dp[x][y],dp[x+1][y]+

蓝桥杯 大臣的旅费_树的最长度_两次DFS

#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <functional> #include <vector> using namespace std; const int maxn = 1000000 + 10; const int INF = 10000000

A. The Fault in Our Cubes 暴力dfs

http://codeforces.com/gym/101257/problem/A 把它固定在(0,0, 0)到(2, 2, 2)上,每次都暴力dfs检查,不会超时的,因为规定在这个空间上,一不行,就会早早退出. 这样写起来比较好写. #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <

codeforces717E Paint it really, really dark gray(树上dfs)

题意: 给你一棵树,2e5个节点,每个节点有一种颜色(黑色或粉色) 让你从节点1开始,自由沿边行走,到达节点时会把这个节点的颜色改变 要求你输出任意一条路径使得从节点1出发,所有节点的颜色都变为黑色 思路: 很明显要递归遍历 每到达一个节点就先改变节点的颜色标志并输出当前节点 如果当前到达了叶子节点,则不用进行操作 返回上层节点时再改变节点的颜色标志并输出当前节点,然后判断叶子节点的颜色,如果为粉色,则再到达一次叶子节点再回到当前节点 这样确保当前节点的所有儿子节点都为黑色的 然后就这样一直递归