中世纪剑士

这个题目很有趣

 

 

n个人决斗,两两之间有强弱关系,强弱关系不传递,例如a>b,b>c,c>a。n个剑士围成一个圈,一次抽签,抽中的人和他右边的人决斗,输了的人出圈。现在问是否存在一种决斗方式让第k个人生出,计算可能胜出的的人数和方案。

 

这个题目让我想起了围成一个圈的猴子的题目,那个题目是约瑟夫问题。

 

和这个不一样。

 

这个题目:一个人要胜出,则要胜了所有右边的人,同时也要胜出左边的人。因为是围成一个圈,所以该人胜出的话,最终肯定是自己跟自己相遇。那么,这种情况下,把圈展开成一个链,将该链延长一倍,如果i和i+n可以相遇,则说明i可以胜出。i人向右决斗,i+n向左决斗

 

如果两个人可以相遇,用meet[i,j]来表示

meet[i,j]= true    if meet[i,k] and meet[k,j] and (e[i,k] or e[j,k])=true

                #ifndef ACIENTSOLDIER_H #define ACIENTSOLDIER_H #include <iostream> #include <memory.h> class AcientSoldier { public: AcientSoldier() { std::cin>>n; a=new int*[n+1]; meet=new bool*[2*n+1]; for(int i=1;i<=n;i++) { a[i]=new int[n+1]; meet[i]=new bool[2*n+1]; meet[i+n]=new bool[2*n+1]; memset(meet[i],0,sizeof(bool)*(2*n+1)); memset(meet[i+n],0,sizeof(bool)*(2*n+1)); meet[i][i+1]=true; meet[i+1][i]=true; meet[i+n][(i+n)%(2*n)+1]=true; meet[(i+n)%(2*n)+1][i+n]=true; for(int j=1;j<=n;j++) std::cin>>a[i][j]; } for(int k=1;k<=2*n;k++) for(int i=1;i<=2*n;i++) for(int j=1;j<=2*n;j++) { if((i<k)&&(j>k)&&meet[i][k]&&meet[k][j]&&a[(i-1)%n+1][(k-1)%n+1]&&a[(j-1)%n+1][(k-1)%n+1]) { meet[i][j]=true; meet[j][i]=true; } } ans=0; for(int i=1;i<=n;i++) { if(meet[i][i+n]) ans++; } std::cout<<ans<<std::endl;; } private: int n; int **a; bool **meet; int ans; }; #endif

[博客整理]

点赞