soj1107 Simple Puzzle 深搜枚举

Description

Here is a simple puzzle on numbers.

There are n numbers, each of which is of k (k$ \ge$n) distinct and significant digits. When the numbers are lined up in n 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 be S.


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. Thus n incomplete numbers are formed with remaining digits keeping digits in the original order. Given the incomplete numbers and the sum S, 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 number c 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


题目大意:

给你相同长度的数,对齐成k列,每个数擦去一个数,每个数擦的列数不同,然后告诉你剩下的不完整的数和这些数的原始的和,求所有可能的原始数据

解题方法:

这道题有毒,找bug找了我一天,数据的读入有是烦的不行,后来我还是改成了从一行字符串里把数一个一个取出来,原来做的是用字符串流的方法,这样前缀0的时候就需要判断,获取数的长度就比较麻烦,最坑的地方是审题啊,题目要求每个数组成的数字各不相同,对齐后列的数字也各不相同,这里没注意,让我找了一天bug,还写了将可行解压入答案时的判重,结果似乎不用判重也能通过,因为每个数的数字都不一样,所以也不用判重,总之就是坑,还有输入数据真的全部都是只有两个数,我改成了每次只读入两个数和一个sum,结果一样能过,,不过我还是觉得应该不能这样写,,比如特殊情况当只输入一个sum09之间,那么是有解的,原始数据就是sum

#include<iostream>
#include<vector>
#include<string>
#include<cstring>
#include<sstream>
#include<algorithm>
#include<cmath>
using namespace std;
int all[15];
int sum=0;
int n; //n个数 
bool row[15];
bool isv[15];
vector<int> v;
vector<vector<int> > ans;
int m;     //m位数 
void dfs(int deep){
	if (v.size()==n){
		//判重很重要啊!!!!!!!横竖都不相同 
		int sum1=0;
		bool vvv[11][11]={0};
		int ppp=m;
		int tmp;
		for (int i=0;i<n;i++){
			sum1+=v[i];
			int tmp=v[i],ttt;
			int pp=0;
			bool iss[10]={0};
			while(tmp!=0){
				ttt=tmp%10;
				tmp/=10;
				if (!iss[ttt]){
					iss[ttt]=1;
				}
				else return;
				if (!vvv[pp][ttt]){
					vvv[pp][ttt]=1;
				}
				else return;
				pp++;
			}
		}
		if (sum1==sum){
			//答案判重,应该是不需要的
			/*
			bool f=true;
			bool f2=false;
			for (int i=0;i<ans.size();i++){
				f=true;
				for (int j=0;j<ans[i].size()&&f;j++){
					if (ans[i][j]!=v[j]) {
						f=false;
					}
				}
				if(f) {
					f2=true;	
					break;
				}
			}
			if (!f2) ans.push_back(v);*/
			ans.push_back(v);
		}
		return ;
	}
	
	for (int i=0;i<10;i++){
		if (!isv[i]){
			isv[i]=1;
			for (int j=0;j<=m;j++){
				//原始数据没有前缀0
				if (i==0&&j==m) continue;
				if (!row[j]){
					//插入一个数
					row[j]=1;
					int p=pow(10,j);
					int a=all[deep];
					int b=a%p;
					a/=p;
					int now=(a*10+i)*p+b; 
					v.push_back(now);
					dfs(deep+1);
					v.pop_back();
					row[j]=0;
				}
			}
			isv[i]=0;
		}
	}
}
bool cmp(vector<int> a,vector<int> b){
	for (int i=0;i<a.size();i++){
		if (a[i]!=b[i]){
			return a[i]<b[i];
		}	
	}
	//return a[1]<b[1];
}
int main(){
	string s;
	int num;
	while(getline(cin,s)){
		if (s=="") continue;
		memset(all,0,sizeof(all));
		n=0;
		int nu=0,num=0;
		bool  f=true,f1=true;
		int k=0;
		for (int i=0;i<s.length();i++){
			if (s[i]==' '){
				if (f){
					num=nu;
					f=false;
					k=0;
					nu=0;
				} 
				else {
					if (f1) {
						f1=false;
						m=k;
					}
					k=0;
					all[n++]=nu;
					nu=0;
				}
			}
			else {
				k++;
				nu=nu*10+s[i]-'0';
			}
		}
		if (num==0) break;
		sum=nu; 
		//只有一个sum输入时
		if(n==0){
			if (sum>=0&&sum<10)
				cout<<num<<" "<<sum<<endl;
			else cout<<num<<' '<<0<<endl;
			continue;
		}
		memset(row,0,sizeof(row));
		memset(isv,0,sizeof(isv));
		v.clear();
		ans.clear();
		dfs(0);
		if (ans.size()==0){
			cout<<num<<' '<<0<<endl;
			continue;
		}
		sort(ans.begin(),ans.end(),cmp);
		for (int i=0;i<ans.size();i++){
			cout<<num;
			for (int j=0;j<n;j++){
				cout<<" "<<ans[i][j];
			}
			cout<<endl;
		}
	}
} 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值