P1092 蟲食算
阿新 • • 發佈:2017-08-23
memset 改變 mem pri ... 輸出 枚舉 字符串 org
題目傳送:https://www.luogu.org/problem/show?pid=1092
#include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #define maxn 30 int n,flag[maxn]; char s[4][maxn]; bool use[maxn]; int id(char ch)//將字符串轉換為數字 { return ch-‘A‘+1; }void dfs(int x,int y,int t)//x代表列,y代表行,t代表進位 { if (x==0) //從上到下,從右到左,x==0表示搜到了最後一列 { if (t==0)//最後一列不能有進位,如果進了以為則第三個字符串會比其他兩個字符串長一位 { for (int i=1;i<n;i++) //如果滿足條件,就輸出 printf("%d ",flag[i]);//輸出 printf("%d\n",flag[n]);//輸出 exit(0); //相當於return 0;程序結束 } return;//返回 } for (int i=x-1;i>=1;i--) //剪枝1 { int w1=flag[id(s[1][i])];//w1表示第一行字符串代表的數字 int w2=flag[id(s[2][i])];//w2表示第二行字符串代表的數字 int w3=flag[id(s[3][i])];//w3表示第三行字符串代表的數字 if (w1==-1||w2==-1||w3==-1) //如果這個位置上還沒被賦值,就返回continue; if ((w1+w2)%n!=w3&&(w1+w2+1)%n!=w3) return; //如果無論進位與否,都不能整除對應的w3就說明字符串不匹配,直接return ; } if (flag[id(s[y][x])]==-1) ////如果這個位置上還沒被賦值,就進行賦值操作 { for (int i=n-1;i>=0;i--) //倒著枚舉更快 if (!use[i]) //如果這個數沒有用過 { if (y!=3) //且不是最後一行 { flag[id(s[y][x])]=i;//就將這個位置賦上值 use[i]=1;//標記這個數用過 dfs(x,y+1,t);//繼續搜索下一行 flag[id(s[y][x])]=-1;//還原 use[i]=0;//還原 } else //當y==3時 { int w=flag[id(s[1][x])]+flag[id(s[2][x])]+t;//兩個數加上它們的進位 if (w%n!=i) continue; use[i]=1;flag[id(s[3][x])]=i;//賦值,標記這個數用過 dfs(x-1,1,w/n);//搜索下一列,進位需要改變 use[i]=0;flag[id(s[3][x])]=-1;//還原 } } } else //如果這個位置上已經被賦值了 { if (y!=3) //繼續搜索 dfs(x,y+1,t); else { int w=flag[id(s[1][x])]+flag[id(s[2][x])]+t; if (w%n!=flag[id(s[3][x])]) //剪枝 2 return; dfs(x-1,1,w/n);//搜索下一列,進位需要改變 } } } int main() { scanf("%d",&n);//讀入n,代表n進制等...... for (int i=1;i<=3;i++) scanf("%s",s[i]+1);//讀入3行字符串 memset(flag,-1,sizeof(flag));//將所有位置標記為未賦值 dfs(n,1,0);//從右往左,上往下搜索,所有從第n列,第1行開始 return 0;//結束 }
P1092 蟲食算