首页 > 代码库 > USTC OJ — 1013 Gizilch(搜索,中等题)

USTC OJ — 1013 Gizilch(搜索,中等题)

1. 题目描述

本题是一道有趣的游戏题,题目背景的描述很是啰嗦,略去不谈。

具体的游戏规则可描述如下:

两个人A和B,A报一个正整数a,B报一个正整数b。其中较大的那个人的游戏角色是擂主,较小的那个人的游戏角色是挑战者。比如:

a = 342, b = 49,显然a > b,那么A就是擂主,B就是挑战者。

那么挑战获胜/失败的规则是什么呢?

我们知道对于任意正整数n,我们都可以把它因子分解,并且可能存在很多中分解形式。比如:

n = 20时,就可以对其因子分解为如下几种形式:

n = 20 * 1 = 10 * 2 = 5 * 4 = 5 * 2 * 2

这里的挑战规则就是:

挑战成功:如果擂主的所有分解形式中,挑战者都存在一种分解,两个分解中存在相同的因子。

挑战失败:如果对于挑战者的所有分解,擂主存在一种分解,该分解中的所有因子都不存在于挑战者的分解中。

2. 算法设计

枚举挑战者的所有因子分解,对每一个分解,枚举擂主的因子分解。

我们用一个标记数组f 来记录某一个因子i 是否已经存在于挑战者的因子分解中,如果存在,f[i] = 1,否则f[i] = 0.

对于f[i] = 1的因子i,我们不可以使用它来分解擂主。

这样依次下去,直到找到一个case:擂主的因子分解顺利完成,那么我们就可以确定擂主获胜,挑战失败。

如果直到枚举完成,也没有找到这样一个case,我们就说擂主落败,挑战成功。

枚举的过程采用深度优先搜索遍历

(注意: 每一个因子只可以出现一次,也就是说因子分解不可以分解成如:20 = 5 * 2 * 2 的形式)

3. AC Code

 1 #include <stdio.h> 2 #include <string.h> 3 #define N 105 4 #define MIN(a, b)   ((a>b)?b:a) 5 #define MAX(a, b)   ((a>b)?a:b) 6  7 int h, l; 8 int f[N]; 9 int is_h_can_be_divided, is_h_divided;10 11 int dfs(int n);12 13 int main()14 {15     int a, b;16     int dfs_ret;17     int winner;18 19     // freopen("in.txt", "r", stdin);20     while ( EOF != scanf("%d%d", &a, &b) )21     {22 23         l = MIN(a, b);24         h = MAX(a, b); 25 26         // f[i] = 0, 初始时,所有1~n都没有被占用27         memset(f, 0, sizeof(f));28         is_h_divided = 0;29         is_h_can_be_divided = 0;30 31         dfs_ret = dfs(l);32 33         // 如果h不能按规则分解,h胜利34         if ( 0 == is_h_can_be_divided )35             winner = h;36         // 如果h能按规则分解,但37         else if ( 1 == is_h_can_be_divided & 1 == dfs_ret )38             winner = h;39         else40             winner = l;41         printf("%d\n", winner);42         43     }44     return 0;45 }46 47 int dfs(int n)48 {49     int n_size;50     int i;51 52     // n == 1时,标识该数分解结束53     if ( 1 == n )54     {55         // is_h_divided 作为h的分解结束标记56         if ( 0 == is_h_divided )57         {58             is_h_can_be_divided = 1;59             is_h_divided = 1;60             if ( dfs(h) )61                 return 1;62             else                    // h没有分解完,并且无法继续分解63             {64                 is_h_divided = 0;65                 return 0;66             }67         }68         return 1;69     }70 71     // 分解n的过程72     n_size = 100 < n ? 100 : n;73     for ( i = 2; i <= n_size; ++i )74     {75         // n % i == 0  <=> i是n的因子76         // f[i]  == 0  <=> i还没有被占用,即保证不会出现20 = 2 * 2 * 5 (i=2)77         if ( 0 == n % i && 0 == f[i] )78         {79             f[i] = 1;80             if ( dfs(n/i) ) return 1;81             f[i] = 0;82         }83     }84     return 0;85 }
View Code

 

USTC OJ — 1013 Gizilch(搜索,中等题)