soj1107 Simple Puzzle 深搜枚举

原创 2016年05月30日 13:17:44

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;
		}
	}
} 


版权声明:本文为博主原创文章,未经博主允许不得转载。

sicily 1107. Simple Puzzle

1107. Simple Puzzle Constraints Time Limit: 10 secs, Memory Limit: 32 MB Description Here is ...

SOJ 1107. Simple Puzzle

Constraints Time Limit: 10 secs, Memory Limit: 32 MB Description Here is a simple puzzle on numbe...

poj2965深搜+枚举

本题大致与poj1753相同,唯一难点是记录翻转过程,其他详见poj1753 //Memory Time //132K 610ms #include #include #includ...

HDU 1426 Sudoku Killer 枚举每一个空,深搜

题意:填数独,横竖1-9不重复,3*3方格1-9不重复(划分好的方格,看图) 想法:开始想着一行一行枚举,然后每行里面的空格再枚举,就是深搜套深搜,后来发现没必要,把空格按照顺序记录下来,往...

POJ-1190-生日蛋糕-DFS(深搜)-枚举-多重剪枝

题目链接: 这个题目很好,有难度;可以好好的多做做; #include #include #include #include #include #include #include #include...
  • wlxsq
  • wlxsq
  • 2015年07月23日 16:46
  • 764

poj1753 枚举+深搜

题目链接:http://poj.org/problem?id=1753本题要注意的就是深搜时的归位问题,以及枚举步数时的最大翻动次数,16是个思维点。//Memory Time //132K ...

Channel Allocation poj1129 (深搜/四色/枚举)

Channel Allocation Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 1506...

SCUT ACM PLACTICE # 3 二进制枚举,深搜,广搜

SCUT ACM PLACTICE # 3 二进制枚举,深搜,广搜

[toj2858]Puzzle Game全排列枚举

题目大意:给一个`4*4`的方格,内有4种字母:A,B,C,D.每种字母有且仅有4个,所以一共是16个字母.每次操作可以交换相邻的两个格子,问至少要操作多少次可以使其中某个2*2的小格子中字母相同. ...

SOJ. Locker puzzle

题目描述                                                                                                ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:soj1107 Simple Puzzle 深搜枚举
举报原因:
原因补充:

(最多只允许输入30个字)