浙大acm问题1003 (转)

原创 2007年09月13日 14:44:00

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

 

Compromise-dp加标记路径

#include #include #include using namespace std; int dp[110][110],mark[110][110],loc[110],cnt;...
  • sileiam
  • sileiam
  • 2013年11月23日 13:19
  • 447

HDU1426 Sudoku Killer(深搜DFS)(很坑的一道题,解数独)

题目: Sudoku Killer Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/...

浙大ACM 1003 Crashing Balloon

这题当时一开始想的很简单,然后碰壁了,后来用递归搞定的。现在拿来看看代码 Crashing Balloon Time Limit: 2 Seconds      Memory Limi...

1003. 我要通过!(20)-浙大PAT乙级真题

1003. 我要通过!(20) “答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于PAT的“答案正确”大派送 —— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误...
  • liuchuo
  • liuchuo
  • 2016年07月22日 14:54
  • 718

浙大PAT乙级 1003. 我要通过!

浙大PAT 1003. 我要通过!

浙大PAT advanced level 1003 emergency

dij的简化版,比较简单。 ---------------------------------------------------------- #include using namespace st...

浙大 PAT Adavnced level 1003. Emergency

As an emergency rescue team leader of a city, you are given a special map of your country. The map s...

浙大PAT (Advanced Level) Practise 1003. Emergency (25)

/*本题是类似于最短路径的一题,只是加了更多变量,采用dijkstra算法的变形即可解题,代码如下:*/ #include using namespace std; #define inf 10000...

浙大pat Advance 1003

#include #include #define MAXLEN 500 using namespace std; typedef struct Node{ int next; //相邻节点的几点...

浙大OJ网址及ACM题目分类

浙大oj网址:http://acm.zju.edu.cn/onlinejudge/ 第一套 动态规划 :ZJU1558 难度:比较简单 博弈问题 :ZJU1913 难度:中等偏难 递归计算 :...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:浙大acm问题1003 (转)
举报原因:
原因补充:

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