Constraints
Time Limit: 10 secs, Memory Limit: 32 MB
Description
Here is a simple puzzle on numbers.
There are n numbers, each of which is of k (kn) distinct and significant digits. When the numbers are lined up inn rows keeping the digits in k columns, the n digits that appear in each column are also distinct. The sum of the numbers is known to beS.
One digit from each number is removed so that not more than one digit is removed from each column. The digits removed are all distinct. Thusn incomplete numbers are formed with remaining digits keeping digits in the original order. Given the incomplete numbers and the sumS, what are the original numbers?
Can you write a program that solves the simple puzzle? The program should find all possible solutions.
Input
Input consists of multiple test cases.
For each test case data is given in one line. The line contains the case number c, the given incomplete numbers followed by the sum S. A space separates two consecutive fields in input.
Input terminates with an input 0 for the case number c.
Output
For each test case, display output in one or more lines. Each line contains the case numberc and a possible solution. A solution consists of the original numbers in the order in which the incomplete numbers appear in input. If there are more than one solution, first output the one with the smallest first number. If there is a tie, first output the one with the smallest second number and so on.
In case it is not possible to solve the puzzle, assume the solution to be 0 and display output accordingly.
Sample Input
1 6 8 174 2 53 81 817 3 3 4 130 0
Sample Output
1 0 2 536 281 3 36 94 3 83 47
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;
struct p{
int n1,n2;
};//保存满足条件的一对数
bool cmp(p t1,p t2){
return t1.n1<t2.n1;
}//用来给sort
p res[1000];//保存所有可能的结果
bool n1[11]; //记录第一个数的数字
bool n2[11]; //记录第二个数的数字
string s1,s2;
int sum,len1,len2;
int base;//有多少结果
void two(int k,int pos){
int num=0;
int tmp_num;
for(int i=0; i < len2; ++i){
num=num*10+(s2[i]-'0');
for(int j=0; j <= 9; ++j){
if(len2-1-i!=pos&&n2[j]==0){
n2[j]=1;
tmp_num=num*10+j;
for(int j=i+1; j < len1; ++j)
tmp_num=tmp_num*10+(s1[i]-'0');
//cout << k << " " << tmp_num << endl;
if(tmp_num+k==sum){//满足结果,保存下来
res[base].n1=k;
res[base].n2=tmp_num;
base++;
}
n2[j]=0;
}
}
}
if(pos!=len2){//保证不重复
for(int i=1; i <= 9; ++i){
if(n2[i]==1)continue;//重复了
//cout << k << " " << i*pow(10,len2)+num << endl;
n2[i]=1;
if(i*pow(10,len2)+num+k==sum){
res[base].n1=k;
res[base].n2=i*pow(10,len2)+num;
base++;
}
n2[i]=0;
}//加在第二个数的开头
}
}
void one(){
int num=0;
int tmp_num;
for(int i=0; i < len1; ++i){
num=num*10+(s1[i]-'0');
for(int j=0; j <= 9; ++j){
if(n1[j]==1)continue;
n1[j]=1;
tmp_num=num*10+j;
for(int j=i+1; j < len1; ++j)
tmp_num=tmp_num*10+(s1[i]-'0');
if(tmp_num<=sum)two(tmp_num,len1-1-i);
n1[j]=0;
}
}//加在第一个数中每个数字的后面
for(int i=1; i <= 9; ++i){
if(n1[i]==1)continue;//重复了
n1[i]=1;
two(i*pow(10,len1)+num,len1);
n1[i]=0;
}//加在第一个数的开头
}//找到合适的第一个数然后级调用two去找第二个数
int main()
{
int c;
while(cin >> c&&c){
bool check=false;
base=0;
cin >> s1 >> s2 >> sum;
len1=s1.length();
len2=s2.length();
memset(n1,0,sizeof(n1));
memset(n2,0,sizeof(n2));
for(int i=0; i < len1; ++i){
if(n1[s1[i]-'0']) {
check=true;
break;
}
else{
n1[s1[i]-'0']=1;
}
}
for(int i=0; i < len2; ++i){
if(n2[s2[i]-'0']) {
check=true;
break;
}
else{
n2[s2[i]-'0']=1;
}
}
//检查输入是否有重复
one();
if(base==0||check) cout << c << " 0" << endl;//没答案或者输入有重复都是不合法的
else{
sort(res,res+base,cmp);
for(int i=0; i < base; ++i){
int dig_n1=0,dig_n2=0,k1=res[i].n1,k2=res[i].n2;\
while(k1!=0){
dig_n1++;
k1/=10;
}
while(k2!=0){
dig_n2++;
k2/=10;
}
//检查是否有前缀0
cout << c << " " ;
if(dig_n1 > len1) cout << res[i].n1;
else cout << "0" << res[i].n1;
if(dig_n2 > len2) cout << " " << res[i].n2 << endl;
else cout << " 0" << res[i].n2 << endl;
}
}
}
}