【NOIP2004】虫食算(搜索+高斯消元)

来源:互联网 发布:淘宝买家仅退款不退货 编辑:程序博客网 时间:2024/06/05 19:03

题意:给定一个n进制的竖式计算(n位数+n位数=n位数),相同字母表示相同的数,不同字母表示不同的数(填数游戏),保证有且仅有唯一解。

做法1:暴力虫食算暴力

做法2:搜索+高斯消元
每一位列一个方程,添加n个未知数,表示每一位的进位状况。
列方程:每一位:两个加数系数为1,和系数为-1,当前这一位系数-n,前一位系数1。
然后跑一遍高斯(肯定是解不出来的,未知数>方程数),然后dfs枚举进位的状态,算出未知数,检验是否合法。

代码:

#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<algorithm>using std::swap;#define MAXN 30int N,finalR,ans[MAXN];char eq[3][MAXN];int A[MAXN][MAXN*2];bool car[MAXN],vis[MAXN];int gcd(int a,int b){return b==0?a:gcd(b,a%b);}int lcm(int a,int b){return a/gcd(a,b)*b;}inline void Init_Matrix(){    memset(A,0,sizeof A);    for(int i=N-1;i>=0;i--)    {        A[i+1][eq[0][i]-'A'+1]++;        A[i+1][eq[1][i]-'A'+1]++;        A[i+1][eq[2][i]-'A'+1]--;        A[i+1][N+i+1]=-N;        A[i+1][N+i+2]=1;        A[i+1][N*2+1]=0;    }}inline void Gauss(){    int r,c,mxr,n=N,m=N*2+1,l,ta,tb;    for(r=1,c=1;r<=n&&c<m;r++,c++)    {        mxr=r;        for(int i=r+1;i<=n;i++)            if(abs(A[i][c])>abs(A[mxr][c]))                mxr=i;        if(A[mxr][c]==0)        {r--;continue;}        if(mxr!=r)swap(A[mxr],A[r]);        for(int i=1;i<=n;i++)            if(i!=r&&A[i][c])            {                l=lcm(abs(A[i][c]),abs(A[r][c]));                ta=l/A[i][c];                tb=l/A[r][c];                for(int j=c;j<=m;j++)                    A[i][j]=A[i][j]*ta-A[r][j]*tb;                if(i<c)                    A[i][i]*=ta;            }    }    finalR=r-1;}inline bool Check(){    memset(vis,0,sizeof vis);    memset(ans,0,sizeof ans);    int sum;    for(int i=N;i>0;i--)    {        sum=A[i][N*2+1];        for(int j=N+1;j<=N*2;j++)            sum-=A[i][j]*car[j-N];        if(sum%A[i][i])return 0;        ans[i]=sum/A[i][i];        if(ans[i]<0||ans[i]>=N||vis[ans[i]])return 0;        vis[ans[i]]=1;    }    for(int i=1;i<N;i++)        printf("%d ",ans[i]);    printf("%d\n",ans[N]);    return 1;}void Enum_carry(int id){    if(id>N)    {        if(Check())            exit(0);        return;    }    car[id]=0;    Enum_carry(id+1);    car[id]=1;    Enum_carry(id+1);}int main(){    scanf("%d%s%s%s",&N,eq[0],eq[1],eq[2]);    Init_Matrix();    Gauss();    Enum_carry(2);    printf("Error\n");    return 0;}
1 2
原创粉丝点击