浙大ZOJ 1003 Crashing Ballon问题解决及其他人的做法

完成了在ZOJ上的处女题,小兴奋,在此记录一下:

一、工程代码加上算法设计注释

--------------------------------------------------crash_ballon.h----------------------------------------------

#ifndef JLU_CCST_GDC_CRASH_BALLON_H
#define JLU_CCST_GDC_CRASH_BALLON_H

extern int whoIsWinner(int player1,int player2,int max);
extern void testWhoIsWinner();

#endif//JLU_CCST_GDC_CRASH_BALLON_H

--------------------------------------------------crash_ballon.cpp----------------------------------------------

/**
题目来源:浙大ACM在线测试——ZOJ,题目编号1003,题名"Crashing Balloon"
URL:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1003
Author:hellogdc<gdcjlu@163.com>
Finish Time:2013.12.31
*/

/**
算法设计:
1. 求出每个数所有的因式分解序列
递归求解——一个数的因式分解序列可以由其因子的因式分解序列构成
2. 检查2个队列的队列的“相容性”
遍历第1个队列的队列,取出每个队列中的元素,做如下处理:
将第2个队列的队列中包含该元素的序列“删除”。
如果遍历完该队列所有元素后,第2个队列中仍然存在一些队列,说明是可行的;否则继续处理下一个队列。
*/
#include <iostream>
#include <list>
using namespace std;
typedef list<int> ListInt;

/**
对n进行因式分解,并输出所有可能的序列,可能会出现重复的序列,但如果按出现位置来考虑的话,那么
每个序列都是唯一的。如果不考虑位置的话,那么每个序列会出现m次(m值是序列长度的阶乘)。
另外,任何一个因式分解序列中不允许出现重复的因子。
另外,该函数不将n本身作为分解序列输出。
一个问题:如果N很大的话,那么意味着要申请一个很大的数组,此时再用数组模拟栈就不合适了,应该真正的
建立一个栈,这样才能使栈的规模大小为所有的节点个数。
返回:所有的序列数目
*/
const int N=10000;
int stack[N];//值为-1,说明该点未在栈中。>=0,则说明该点在栈中。
int top=0;//指向栈顶
static int decompose(int n){
	int count=0;
	for(int i=2;i<n;i++){
		bool flag=true;
		if(n%i==0){
			//保证这2个要入栈的点不是同一个点
			if( i==(n/i) )
				flag=false;
			//检查下面2个要入栈的点是否已经在栈中出现,如出现,则该分解不合法,返回。			
			int head=top;			
			while(flag&&stack[head]>=0){
				if(head==i||head==n/i){
					flag=false;
					break;
				}
				head=stack[head];
			}
			if(!flag)
				continue;
			//入栈——树边			
			stack[i]=top;
			top=i;
			count+=decompose(n/i);
			//入栈——树节点			
			stack[n/i]=top;
			top=n/i;
			//输出栈内容
			head=top;
			while(stack[head]>=0){
				cout<<head<<'\t';
				head=stack[head];
			}
			cout<<endl;
			//2次弹栈——弹出压入栈的树边和树节点
			int tmp=top;
			top=stack[top];
			stack[tmp]=-1;
			tmp=top;
			top=stack[top];
			stack[tmp]=-1;

			count++;
		}
	}
	return count;
}

/**
基于decompose()函数遇到的问题——不能处理数据值很大的问题,利用list来模拟“栈”。
另外,加一个参数max,用来设置因子的上限。如果因子分解序列中某个因子大于这个
上限,那么这个序列就可以舍去了。
返回:所有的序列数目
*/
ListInt listForStack;
static int decomposeOptimizationWithList(int n,int max){
	int count=0;
	ListInt::iterator it;
	for(int i=2;i<n;i++){
		bool flag=true;
		if(n%i==0){
			//保证每个因子比max小
			if(i>max)
				flag=false;
			//保证这2个要入栈的点不是同一个点
			if( i==(n/i) )
				flag=false;
			//检查下面2个要入栈的点是否已经在栈中出现,如出现,则该分解不合法,返回。	
			for(it=listForStack.begin();it!=listForStack.end();it++){
				if(*it==i||*it==n/i){
					flag=false;
					break;
				}
			}
			if(!flag)
				continue;
			//入栈——树边	
			listForStack.push_front(i);
			count+=decomposeOptimizationWithList(n/i,max);
			if( (n/i) <=max ){//如果该“树节点”因子比max小,则入栈,并且输出
				//入栈——树节点			
				listForStack.push_front(n/i);
				//输出栈内容
				for(it=listForStack.begin();it!=listForStack.end();it++)
					cout<<*it<<'\t';			
				cout<<endl;
				//2次弹栈——弹出压入栈的树边和树节点
				listForStack.pop_front();	
				count++;
			}
			listForStack.pop_front();
		}		
	}
	return count;
}

/**
decompose()和decomposeOptimizationWithList()都会存在一个问题,那就是因式分解序列的重复
出现(不考虑因子出现的次序)。
考虑到每个序列以因子的各种顺序形式出现,那么如果我想得到唯一的一个序列,只要让因子以递增
顺序排列即可。
整个序列的递增顺序可以转换为每次加入元素时,都要确保该元素比“栈”顶元素小
*/
ListInt listForStackUnique;
static int decomposeUnique(int n,int max){
	int count=0;
	ListInt::iterator it;
	for(int i=2;i<n;i++){
		bool flag=true;
		if(n%i==0){
			//保证每个因子比max小
			if(i>max)
				flag=false;
			//保证这2个要入栈的点不是同一个点
			if( i==(n/i) )
				flag=false;
			//检查下面2个要入栈的点是否已经在栈中出现,如出现,则该分解不合法,返回。	
			for(it=listForStackUnique.begin();it!=listForStackUnique.end();it++){
				if(*it==i||*it==n/i){
					flag=false;
					break;
				}
			}
			if(!flag)
				continue;
			//入栈——树边	
			//每次入栈前,做一次大小判断
			if( (!listForStackUnique.empty()) && i>listForStackUnique.front() )
				continue;
			listForStackUnique.push_front(i);
			count+=decomposeUnique(n/i,max);
			if( (n/i) <=max && //如果该“树节点”因子比max小,则入栈,并且输出
				(listForStackUnique.empty()||(n/i)<listForStackUnique.front())){//每次入栈前,做一次大小判断
					//入栈——树节点				
					listForStackUnique.push_front(n/i);
					//输出栈内容
					for(it=listForStackUnique.begin();it!=listForStackUnique.end();it++)
						cout<<*it<<'\t';			
					cout<<endl;
					//2次弹栈——弹出压入栈的树边和树节点
					listForStackUnique.pop_front();	
					count++;
			}
			listForStackUnique.pop_front();
		}		
	}
	return count;
}

/**
基于decomposeUnique()函数,获取数的因式分解序列,不过这次不是输出,而是保存到队列中
*/
ListInt listForStackUniqueForGetValue;
static int getValueDecompisitionList(int n,int max,list<ListInt*>* deList){
	int count=0;
	ListInt::iterator it;
	for(int i=2;i<n;i++){
		bool flag=true;
		if(n%i==0){
			//保证每个因子比max小
			if(i>max)
				flag=false;
			//保证这2个要入栈的点不是同一个点
			if( i==(n/i) )
				flag=false;
			//检查下面2个要入栈的点是否已经在栈中出现,如出现,则该分解不合法,返回。	
			for(it=listForStackUniqueForGetValue.begin();it!=listForStackUniqueForGetValue.end();it++){
				if(*it==i||*it==n/i){
					flag=false;
					break;
				}
			}
			if(!flag)
				continue;
			//入栈——树边	
			//每次入栈前,做一次大小判断
			if( (!listForStackUniqueForGetValue.empty()) && i>listForStackUniqueForGetValue.front() )
				continue;
			listForStackUniqueForGetValue.push_front(i);
			count+=getValueDecompisitionList(n/i,max,deList);
			if( (n/i) <=max && //如果该“树节点”因子比max小,则入栈,并且输出
				(listForStackUniqueForGetValue.empty()||(n/i)<listForStackUniqueForGetValue.front())){//每次入栈前,做一次大小判断
					//入栈——树节点				
					listForStackUniqueForGetValue.push_front(n/i);				

					//将队列内容保存到deList中
					ListInt* tmpList=new ListInt(listForStackUniqueForGetValue.size());
					ListInt::iterator tmpIt=tmpList->begin();
					for(it=listForStackUniqueForGetValue.begin();it!=listForStackUniqueForGetValue.end();it++,tmpIt++)
						*tmpIt=*it;
					deList->push_front(tmpList);

					//弹栈——弹出压入栈的树节点
					listForStackUniqueForGetValue.pop_front();	
					count++;
			}
			//弹栈——弹出压入栈的树边点
			listForStackUniqueForGetValue.pop_front();
		}		
	}
	return count;
}

/**
比较二者之间谁能获胜。
处理:
1. 如果二者数值相等,则无法判断谁为赢家,返回-1
2. 如果二者均不能在规定的最大值因子下获得因式分解序列,则值较大的为赢家
3. 如果一人可以得到合法的因式分解序列,而另一人没得到,则赢家为拥有合法序列的玩家
4. 如果二者均有合法序列,则按照低分者计算正确,来分析高分者的因式分解序列是否合理
	如何判断:遍历低分者的所有因式分解序列,对该序列中的每个元素做如下处理:
	4.1 遍历高分者的所有因式分解序列,将包含该元素的所有序列删除(其实是放进另一个备份队列中)。
	4.2 遍历完后,如果高分者队列不为空,说明存在一个合法的序列与该低分者的序列对应,则说明高分者为赢家;
		否则,根据备份队列还原高分者队列内容,继续处理低分者队列中的下一个序列。


返回:-1表示无赢家;否则,将返回赢家的数值
*/
int whoIsWinner(int player1,int player2,int max){
	int winner=-1;
	bool isWinnerFound=false;

	int lowPlayer=player1,highPlayer=player2;
	if(player1==player2)//无赢家
		return -1;
	if(player1>player2){
		lowPlayer=player2;
		highPlayer=player1;
	}
	list<ListInt*>* lowList=new list<ListInt*>();
	list<ListInt*>*	highList=new list<ListInt*>();

	list<ListInt*>* highListBack1=new list<ListInt*>();//存放高分者队列中被移除的元素
	list<ListInt*>* highListBack2=new list<ListInt*>();//存放高分者队列中剩下的元素

	ListInt* valueSelf=NULL;
	int count=-1;
	count=getValueDecompisitionList(lowPlayer,max,lowList);
	if(lowPlayer<=max){
		valueSelf=new ListInt(1,lowPlayer);
		lowList->push_front(valueSelf);
		count++;
	}
	//检查低分者是否计算错误
	if(count<=0)
		lowPlayer=highPlayer;//说明该低分者不可能为赢家,则赢家只能为高分者
	count=getValueDecompisitionList(highPlayer,max,highList);
	if(highPlayer<=max){
		valueSelf=new ListInt(1,highPlayer);
		highList->push_front(valueSelf);
		count++;
	}
	//检查高分者是否撒谎
	if(count<=0){
		winner= lowPlayer;
		isWinnerFound=true;
	}
	if(!isWinnerFound){
		//因为低分者都说真话,那么基于低分者的因式分解序列队列,对高分者的因式分解队列进行检查
		for(list<ListInt*>::iterator it=lowList->begin();it!=lowList->end()&&(!isWinnerFound);it++){
			//依据低分者队列的每个合法序列的每个元素,来剔除掉高分者队列中的相应序列
			for(list<int>::iterator itt=(*it)->begin();itt!=(*it)->end()&&(!highList->empty());itt++){			
				while(!highList->empty()){				
					ListInt* top=highList->front();
					highList->pop_front();
					//检查该序列中是否包含低分者序列中的值
					bool isRemove=false;
					for(list<int>::iterator highIt=top->begin();highIt!=top->end();highIt++){
						if(*itt==*highIt){
							isRemove=true;
							break;
						}
					}
					if(isRemove)
						highListBack1->push_front(top);
					else
						highListBack2->push_front(top);
				}
				//切换队列指针
				list<ListInt*>* tmp=highListBack2;
				highListBack2=highList;//该队列在每次循环开始时,都为空队列
				highList=tmp;				
			}
			//检查高分者队列中是否还存在可行的因式分解序列
			if(!highList->empty()){
				isWinnerFound=true;
				winner=highPlayer;
				break;
			}else{
				//还原高分者队列,继续处理低分者队列中的下一个序列
				list<ListInt*>* tmp=highListBack1;
				highListBack1=highList;
				highList=tmp;
			}
		}
	}
	if(!isWinnerFound)//说明对于低分者的所有合法序列,高分者中都不存在对应的合法序列,说明高分者在撒谎
		winner=lowPlayer;
	//清空队列
	while(!highList->empty()){
		ListInt* top=highList->front();
		highList->pop_front();
		delete top;
	}
	while(!lowList->empty()){
		ListInt* top=lowList->front();
		lowList->pop_front();
		delete top;
	}
	while(!highListBack1->empty()){
		ListInt* top=highListBack1->front();
		highListBack1->pop_front();
		delete top;
	}
	while(!highListBack2->empty()){
		ListInt* top=highListBack2->front();
		highListBack2->pop_front();
		delete top;
	}
	delete highList;
	delete lowList;
	delete highListBack1;
	delete highListBack2;

	return winner;
}

static void testDecompseFunc(){
	for(int i=0;i<N;i++)
		stack[i]=-1;
	int count=0;
	cout<<"**********************decompose************************************"<<endl;	
	count=decompose(500);
	cout<<"Count="<<count<<endl;
	cout<<"**********************decomposeOptimizationWithList*****************"<<endl;	
	count=decomposeOptimizationWithList(500,100);
	cout<<"Count="<<count<<endl;
	cout<<"**********************decomposeOptimizationWithList******************"<<endl;	
	count=decomposeOptimizationWithList(500,1000);
	cout<<"Count="<<count<<endl;
	cout<<"*********************decomposeUnique******************"<<endl;	
	count=decomposeUnique(42,1000);
	cout<<"Count="<<count<<endl;
	cout<<"*******************getValueDecompisitionList**********************"<<endl;
	list<ListInt*> deList;
	count=getValueDecompisitionList(42,1000,&deList);
	for(list<ListInt*>::iterator it=deList.begin();it!=deList.end();it++){
		for(ListInt::iterator tmpIt=(*it)->begin();tmpIt!=(*it)->end();tmpIt++)
			cout<<*tmpIt<<'\t';
		cout<<endl;
		delete (*it);
	}
	cout<<"Count="<<count<<endl;
}

void testWhoIsWinner(){
	int player1=343,player2=49;
	int winner;
	cout<<"player1="<<player1<<endl;
	cout<<"player2="<<player2<<endl;
	winner=whoIsWinner(player1,player2,100);
	if(winner==-1)
		cout<<"the challenge would not be upheld"<<endl;
	else
		cout<<"winner="<<winner<<endl;
	cout<<"**************************************************************"<<endl;
	player1=3559,player2=610;
	cout<<"player1="<<player1<<endl;
	cout<<"player2="<<player2<<endl;
	winner=whoIsWinner(player1,player2,100);
	if(winner==-1)
		cout<<"the challenge would not be upheld"<<endl;
	else
		cout<<"winner="<<winner<<endl;
	cout<<"**************************************************************"<<endl;
	player1=62,player2=36;
	cout<<"player1="<<player1<<endl;
	cout<<"player2="<<player2<<endl;
	winner=whoIsWinner(player1,player2,100);
	if(winner==-1)
		cout<<"the challenge would not be upheld"<<endl;
	else
		cout<<"winner="<<winner<<endl;
	cout<<"**************************************************************"<<endl;
	player1=10001,player2=10003;
	cout<<"player1="<<player1<<endl;
	cout<<"player2="<<player2<<endl;
	winner=whoIsWinner(player1,player2,100);
	if(winner==-1)
		cout<<"the challenge would not be upheld"<<endl;
	else
		cout<<"winner="<<winner<<endl;
}

--------------------------------------------------main.cpp----------------------------------------------

#if 0
#include "crash_ballon.h"
int main(){
	testWhoIsWinner();
	return 0;
}
#endif



二、提交并被ZOJ成功接受的代码——算法核心代码

--------------------------------------------------submmit_main.cpp----------------------------------------------

#include <iostream>
#include <list>
using namespace std;
typedef list<int> ListInt;
static ListInt listForStackUniqueForGetValue;
static int getValueDecompisitionList(int n,int max,list<ListInt*>* deList){
	int count=0;
	ListInt::iterator it;
	for(int i=2;i<n;i++){
		bool flag=true;
		if(n%i==0){
			if(i>max)
				flag=false;
			if( i==(n/i) )
				flag=false;
			for(it=listForStackUniqueForGetValue.begin();it!=listForStackUniqueForGetValue.end();it++){
				if(*it==i||*it==n/i){
					flag=false;
					break;
				}
			}
			if(!flag)
				continue;
			if( (!listForStackUniqueForGetValue.empty()) && i>listForStackUniqueForGetValue.front() )
				continue;
			listForStackUniqueForGetValue.push_front(i);
			count+=getValueDecompisitionList(n/i,max,deList);
			if( (n/i) <=max &&
				(listForStackUniqueForGetValue.empty()||(n/i)<listForStackUniqueForGetValue.front())){
					listForStackUniqueForGetValue.push_front(n/i);
					ListInt* tmpList=new ListInt(listForStackUniqueForGetValue.size());
					ListInt::iterator tmpIt=tmpList->begin();
					for(it=listForStackUniqueForGetValue.begin();it!=listForStackUniqueForGetValue.end();it++,tmpIt++)
						*tmpIt=*it;
					deList->push_front(tmpList);
					listForStackUniqueForGetValue.pop_front();
					count++;
			}
			listForStackUniqueForGetValue.pop_front();
		}
	}
	return count;
}
static int whoIsWinner(int player1,int player2,int max){
	int winner=-1;
	bool isWinnerFound=false;
	int lowPlayer=player1,highPlayer=player2;
	if(player1==player2)
		return player1;
	if(player1>player2){
		lowPlayer=player2;
		highPlayer=player1;
	}
	list<ListInt*>* lowList=new list<ListInt*>();
	list<ListInt*>*	highList=new list<ListInt*>();
	list<ListInt*>* highListBack1=new list<ListInt*>();
	list<ListInt*>* highListBack2=new list<ListInt*>();
	ListInt* valueSelf=NULL;
	int count=-1;
	count=getValueDecompisitionList(lowPlayer,max,lowList);
	if(lowPlayer<=max){
		valueSelf=new ListInt(1,lowPlayer);
		lowList->push_front(valueSelf);
		count++;
	}
	if(count<=0)
		lowPlayer=highPlayer;
	count=getValueDecompisitionList(highPlayer,max,highList);
	if(highPlayer<=max){
		valueSelf=new ListInt(1,highPlayer);
		highList->push_front(valueSelf);
		count++;
	}
	if(count<=0){
		winner= lowPlayer;
		isWinnerFound=true;
	}
	if(!isWinnerFound){
		for(list<ListInt*>::iterator it=lowList->begin();it!=lowList->end()&&(!isWinnerFound);it++){
			for(list<int>::iterator itt=(*it)->begin();itt!=(*it)->end()&&(!highList->empty());itt++){
				while(!highList->empty()){
					ListInt* top=highList->front();
					highList->pop_front();
					bool isRemove=false;
					for(list<int>::iterator highIt=top->begin();highIt!=top->end();highIt++){
						if(*itt==*highIt){
							isRemove=true;
							break;
						}
					}
					if(isRemove)
						highListBack1->push_front(top);
					else
						highListBack2->push_front(top);
				}
				list<ListInt*>* tmp=highListBack2;
				highListBack2=highList;
				highList=tmp;				
			}
			if(!highList->empty()){
				isWinnerFound=true;
				winner=highPlayer;
				break;
			}else{
				list<ListInt*>* tmp=highListBack1;
				highListBack1=highList;
				highList=tmp;
			}
		}
	}
	if(!isWinnerFound)
		winner=lowPlayer;
	while(!highList->empty()){
		ListInt* top=highList->front();
		highList->pop_front();
		delete top;
	}
	while(!lowList->empty()){
		ListInt* top=lowList->front();
		lowList->pop_front();
		delete top;
	}
	while(!highListBack1->empty()){
		ListInt* top=highListBack1->front();
		highListBack1->pop_front();
		delete top;
	}
	while(!highListBack2->empty()){
		ListInt* top=highListBack2->front();
		highListBack2->pop_front();
		delete top;
	}
	delete highList;
	delete lowList;
	delete highListBack1;
	delete highListBack2;
	return winner;
}
#if 1
int main(){
	int player1=343,player2=49;
	int winner;
	while( cin>>player1>>player2 ){
		winner=whoIsWinner(player1,player2,100);
		cout<<winner<<endl;
	}
	return 0;
}
#endif



注:刚开始提交的时候,ZOJ提示“Wrong Answer”,上网上看了别人实现该题的代码,发现自己在2个数值相等的情况下,没处理好。在这种情况下,直接将值输出就行,而我则是返回-1,说明无法进行比较,结果是多次一举。将这个处理改完之后,提交,就被成功接受了。


三、网上别人的代码

原文地址:http://blog.csdn.net/jayfer/article/details/1783649


1003问题,本来以为要用数论的某些东西来解,但是想了好久都没有找到一个好的算法。惭愧本人能力有限,于是在网上找到了些解法。

以下是网上搜到的解法:

原来帖在ZJU的讨论区里了   今天再往这里帖一次   请大家提出意见:)   
    
  (*)ZJU   1003   -   Crashing   Balloon   -   00:00.18   688K   
  http://acm.zju.edu.cn/show_problem.php?pid=1003   
  WA   2次   AC   1次   
  这道题我初看的时候想找数学方法,不过看来行不通。用回溯搜索就可以了。   
    
  先将题目判断胜负的标准列出来:   
  1.如果肯定获胜者说谎而挑战者说真话,则挑战者成功。   
  2.如果获胜者和挑战者都有可能说了真话,则挑战者失败。   
  3.如果挑战者说谎,挑战者失败。   
    
  列表就是:   
  获胜者 挑战者 胜方   
   假   真  挑战者   
   真   真  获胜者   
       假  获胜者     
    
  作法1:那我们只需要先判断挑战者的分数是否能正确分解,不能则输出获胜者的分数。能则进行搜索,先将获胜者的分数进行分解,将用过的因数标记,分解成某一形式后检查挑战者的分数是否能分解为剩下的因数之积。能,说明获胜者有说真话的情况,输出获胜者的分数。一直不能或是获胜者的分数无法分解,说明获胜者说假话,输出挑战者的分数。(见Starfish的程序)   
    
  作法2:用回溯搜索,从2开始一直搜索因数到100。设获胜者的分数为m,挑战者的分数为n(m>n),当前搜索到的因数为p,flag1为是否两人分数能分解成一合法形式,flag2为挑战者的分数是否符合要求。搜索函数为f(m,   n,   p),初始时flag1   =   flag2   =   FALSE。由于每个因数只能出现一次,所以:如果p|m,则f(m   DIV   p,   n,   p+1),如果p|n,则f(m,   n   DIV   p,   p+1)。还有可能不分解出因数p,所以当p<m或p<n时,f(m,   n,   p+1)。当搜索到m=1且n=1时,说明存在一种没有出现相同因数的分解,设flag1为TRUE。如果发现n=1,则挑战者的分数可以分解,符合要求,设为TRUE。最后的分析表格同上表。优化:flag1和flag2的初始状态都是FALSE,我们由上面的分析可以发现,flag1只要变成TRUE,最后的答案也就定下来了,于是,当flag1发生改变时就可以退出搜索了。(见Bamboo或我的程序)   
    
  错误总结:第一次错在“如果搜索到m和n在2-100之间且m和n相等时,说明存在出现相同因数的情况,设flag2为TRUE”,反例:12   =   2*6   =   3*4。由此发现,是否出现相同因数并不好计算。还有读题目的时候也没理解好,第3点错了。   
    
  另:附有Bamboo,Starfish的代码。我和代码和Bamboo的一样。还有Idler的经验:他的程序和我的几乎一样,但是速度飞快,从大到小搜一般都比较快!最好是看Starfish的代码。

 

这里附上找到的代码:

 

#include  < stdio.h >


int  flag1,flag2;
// flag1为是否两人分数能分解成一合法形式,flag2为挑战者的分数是否符合要求
void  dfs (  int  n ,  int  m ,  int  fac )
{
    
if(flag1== 1 )
        
return ;
    
if(m==1 && n==1 )
    
{
        flag1
=1;
        flag2
=1;
        
return;
    }

    
if(m==1)
        flag2
=1;
    
if(fac<2 )      
        
return;
    
if(n%fac==0)
        dfs(n
/fac,m,fac-1);
    
if(m%fac== 0 )
        dfs(n,m
/fac,fac-1);
    dfs(n,m,fac
-1);
}


int  main()
{
    
int tmp,n,m;
    
while(scanf("%d %d",&n,&m)!=EOF)
    
{
        
if(m>n)
        
{
            tmp
=m;
            m
=n;
            n
=tmp;
        }

        flag1
=flag2=0;
        dfs(n,m,
100);
        
if(flag1||!flag2)
            printf(
"%d ",n);
        
else if(flag2==1&&flag1==0)
            printf(
"%d ",m);
    }

    
return 0;
}

 

以上是非常简单的算法。用的是就是回溯搜索。

我当时看懂后,感觉豁然一亮!



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1584638





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值