题解 P1013 【进制位】

------------恢复内容开始------------
别说这是个人第一篇题解c++

AC记录优化

13ms / 688.00KB ,其实能够说还算快的吧。spa


题目再次复述code

1.字母都不一样
2.在限定进制内加减法
3.第一行第一列字母排列相等

有些人这么想,枚举每个字母,不过--blog

正常人应该能够明白进制为nget

仔细分析一下,能够发现每一个字母\(ch\)\(0 \leq ch \leq n-1\)it

那不就是迎刃而解接了吗?class

  1. 每一个字母依次赋与\(0\)\((n-1)\)sed

  2. 依次判断是否符合im

note:本人码风可能有点丑

#include<bits/stdc++.h>
#define INF 1e9
using namespace std;
const int N=12,M=100;
char s[N][N][M];// s[i][j][k]为第i行第j列的第k个字母
int num[M];
int n;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=26;i++) num[i]=INF;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            scanf("%s",s[i][j]+1);
    for(int i=2;i<=n;i++) num[s[1][i][1]-'A'+1]=i-2;  //每一个字母一侧赋值
    for(int i=2;i<=n;i++)
        for(int j=2;j<=n;j++){//两两配对
            int combine1=num[s[1][j][1]-'A'+1];
            int combine2=num[s[i][1][1]-'A'+1];
            int len=strlen(s[i][j]+1);

            int p1=0,t=1;
            for(int k=1;k<=len;k++){
                p1+=num[s[i][j][len-k+1]-'A'+1]*t;
                t*=(n-1);
            }//两数之和转为n进制

            int p2=combine1+combine2//字母权相加
            if(p1!=p2){
                puts("ERROR!");
                return 0;
            }
        }
    for(int i=2;i<=n;i++){
        printf("%c=%d",s[1][i][1],num[s[1][i][1]-'A'+1]);//输出
        if(i!=n) printf(" ");
    }
    printf("\n%d\n",n-1);
    return 0;
}

尚未结束。。。
P1013 进制位

是什么缘由呢?

呵呵。

谁说的必须依次赋值?

每一个字母依次赋与\(0\)\((n-1)\)

但不能重复哦!

#include<bits/stdc++.h>
#define INF 1e9
using namespace std;
const int N=12,M=100;
int n;
char s[N][N][M];
int num[M];//第i个字母的赋值
bool used[M]; //i数是否用过
int sol(int t){
    if(t>n){
        bool f=false;
        for(int i=2;i<=n;i++){
            for(int j=2;j<=n;j++){
                int combine1=num[s[1][j][1]-'A'+1];
                int combine2=num[s[i][1][1]-'A'+1];
                int len=strlen(s[i][j]+1);
    
                int p1=0,t=1;
                for(int k=1;k<=len;k++){
                    p1+=num[s[i][j][len-k+1]-'A'+1]*t;
                    t*=(n-1);
                }
    
                int p2=combine1+combine2;
                if(p1!=p2){
                    f=true;
                    break;
                }//上段就是比较
            }
            if(f) break;
        }
        if(!f){
            for(int i=2;i<=n;i++){
                printf("%c=%d",s[1][i][1],num[s[1][i][1]-'A'+1]);
                if(i!=n) printf(" ");
            }
            printf("\n%d\n",n-1);
            return -1;
        }//上段就是输出
        return 0;
    }
    for(int i=0;i<n-1;i++) if(!used[i]){
        used[i]=true;
        num[s[1][t][1]-'A'+1]=i;//放进去
        int nw=sol(t+1);
        if(nw==-1) return -1;//回朔
        num[s[1][t][1]-'A'+1]=INF;
        used[i]=false;
    }
    return 0;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=26;i++) num[i]=INF;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            scanf("%s",s[i][j]+1);
    memset(used,0,sizeof(used));
    int nw=sol(2);//结束了吗?
    if(nw!=-1) puts("ERROR!");
    return 0;
}

终于作完了,分析一下时间复杂度

\(O(n!·n^2·Len) (n \leq 9)\)

(我长度算的3)

再加上一些杂七杂八的优化,\(break\),稳稳的就\(AC\)了。
------------恢复内容结束------------

相关文章
相关标签/搜索