这个题目是搜索的经典题目,深搜来找到解进而进行两个姐相容性的判定。
#include<stdio.h>
#include<iostream>
using namespace std;
bool flag;
bool check(int big,int small,int n)
{
int i;
for(i=n;i>1;i--)
{
if(small%i==0){
if(check(big,small/i,i-1))return true;
}
if(big%i==0){
if(check(big/i,small,i-1))return true;
}
}
if(small == 1){ //分数少者有可能没有说谎
flag = true;
}
else if(!flag){ //如果分少的说谎了(包含了分数多者说谎的情况)
return true;
}
if(big==1&&small==1){ //两个人的分数相容
return true;
}
return false; //得分少者的分数能被分解结束了,但是得分大不能被分解,返回上一层继续搜索相容的情况
}
int main()
{
int a,b;
while(scanf("%d%d",&a,&b)!=EOF)
{
int big,small;
flag = false;
big = a>b?a:b;
small = a>b?b:a;
int win=big;
if(!check(big,small,100))
{
win=small;
}
printf("%d\n",win);
}
return 0;
}
(1)为什么这样做呢?由于情况有很多种,如果你要用数组记录所有的可能的情况,至少得开一个100*100的二维数组,还有可能就是给出的数字很大,进行因式分解是不好处理的,应为这个题目要求的数字绝对不能出现两个相同数字的乘积。如果求出两个所有可能的情况,进行比兑,但是这种思想实在不知道怎么样操作。一种办法就是用nlog(n)的方法进行解的搜索。如果找到一个这两个数的两种可能的分解方案,就进行判定,这两个方案是否相容,如果相容则可以得出结果;如果不相容,继续找相容的情况了。算法的时间复杂度是(nLog(n))。这个题目需要想清楚的地方就是,如果判断解是否相容。判断解相容有下列几种情况:
1》如果小的数字到一,可以认为小的没有撒谎。此时要判定大的分数是否被整除到一。如果大的被整除到一,说明这种情况下,这两个分数是相容的,判定大的赢;如果没有被整除到一,显然大的在说谎,此时由于不知道小的是否在说谎,所以返回上一层,再进行判断,找有没有跟大的分数相容的情况,如果有,就判断大的赢,显然这种情况是不存在的,可以直接判断小的赢,这里存在一个剪枝,但是在程序中没有体现出来。
2》如果小的数字没到一。显然说谎了,那么就判定分数大的赢了;
(2)这个方法还有说明改进的地方?
(3)还有没有其他的方法呢?