A、B、C、D、E、F、G、H、I、J 共10名学生有可能参加本次计算机竞赛,也可能不参加。因为某种原因,他们是否参赛受到下列条件的约束:
A、B、C、D、E、F、G、H、I、J 共10名学生有可能参加本次计算机竞赛,也可能不参加。因为某种原因,他们是否参赛受到下列条件的约束:
   1. 如果A参加,B也参加;
   2. 如果C不参加,D也不参加;
   3. A和C中只能有一个人参加;
   4. B和D中有且仅有一个人参加;
   5. D、E、F、G、H 中至少有2人参加;
   6. C和G或者都参加,或者都不参加;
   7. C、E、G、I中至多只能2人参加   
   8. 如果E参加,那么F和G也都参加。
   9. 如果F参加,G、H就不能参加
   10. 如果I、J都不参加,H必须参加
请编程根据这些条件判断这10名同学中参赛者名单。如果有多种可能,则输出所有的可能情况。每种情况占一行。参赛同学按字母升序排列,用空格分隔。答案就是一种可能的情况。
public class CS {    private static long data = 0x3FF;    public static void main(String[] args) {
        
        boolean state = true;
        
        for(;data>=0;data--){
            
            state = true;
            
            // 如果A参加,B也参加;
            state = (getState('A') && getState('B') ) || !getState('A') ?  state : false;
            
            // 如果C不参加,D也不参加;
            state = ( !getState('C') && !getState('D') )  || getState('C') ?  state : false;
            
            // A和C中只能有一个人参加
            state = ( getState('A') != getState('C') ) || (!getState('A') && getState('C')) ?  state : false;
            
            // B和D中有且仅有一个人参加
            state = getState('B') != getState('D') ?  state : false;
            
            // D、E、F、G、H 中至少有2人参加;
            Boolean [] defgh = {getState('D'),getState('E'),getState('F'),getState('G'),getState('H')};
            int num = 0;
            for(boolean b : defgh){
                if(b){
                    num++;
                }
            }
            state = num>=2 ? state : false;
            
            // C和G或者都参加,或者都不参加;
            state = getState('C') == getState('G') ?  state : false;
            
            // C、E、G、I中至多只能2人参加
            Boolean [] ceghi = {getState('C'),getState('E'),getState('G'),getState('I')};
            num = 0;
            for(boolean b : ceghi){
                if(b){
                    num++;
                }
            }
            state = num==2 ? state : false;
            
            // 如果E参加,那么F和G也都参加。
            state = (getState('E') && getState('F') && getState('G') ) ||  !getState('E') ? state : false;
            
            // 如果F参加,G、H就不能参加
            state = (getState('F') && !getState('G') && !getState('H') ) ||  !getState('F') ? state : false;
            
            // 如果I、J都不参加,H必须参加
            state = (!getState('I') && !getState('J') && getState('H') ) ||  getState('I')  || getState('J') ? state : false;
            
            if(state){
                print();
            }
        }
    }
    
    //data 的从低位到高位分别表不A-J,1表示参加,0表示不参加
    private static boolean getState(char c){
        int p = c-'A';
        long b = 1<< p;
        return (data & b ) != 0;
    }
    
    //输出可行的方案
    private static void print(){        
        char[] chars = {'A','B','C','D','E','F','G','H','I','J'};
        for(int i =0;i<chars.length;i++){
            if(getState(chars[i])){
                System.out.print(" "+chars[i]);
            }
        }
        System.out.println();
    }
    }
//
这道题实在看不懂,还望高手一一指点,还有关于位移的运算一般都用在什么地方,到底怎么办,如果方便的话请加QQ细细说明,做个朋友,1215811695

解决方案 »

  1.   

    你看不明白的就是getState那段吧他用位操作只是为了方便data表示参赛情况,每一位表示某个人的参加情况 最开始是0x3ff也即1111111111表示'A'到'J'都参加
    主循环每次递减就是不断遍历各种情况getState中 p表示传入函数中的是第几个人
    b = 1 << p 表示将1左移p位, 比如 传入'C', p = 2, b = 100, data & b的结果为 (以0x3ff为例)100 != 0
    也就是说 C参加比赛  没问题了吧?
      

  2.   

    首先要知道这是一种2进制思路,A-J的参加或不参加分别用1,0表示,
    那么,如果都参加,就相当于1111111111,如果都不参加就相当于0000000000
    好了这就是最大状态和最小状态,也就是符合题意的状态在0000000000到1111111111之间
    11111111111的二进制也就是16进制的3FF,00000000000也就是10进制的0
    所以程序中使用了long data = 0x3FF; 
    然后循环,每次data-1,直到data==0结束,也就是在0000000000到1111111111之间查找,分别通过各种约束条件过滤数据,这就是主程序的部分再来看getState(char c)
    1111111111假设分别对应JIHGFEDCBA的参赛状态,那么A的状态就是最右边的1,B的右数第二个,C是右数第三个,等等,这样通过移位来找到每个字母对应的状态,对于参数传进来的c,通过计算c-'A',可以得到该字母的右数的位置,比如'A'-'A'=0,'B'-'A'=1,'C'-'A'=2等等,用来确定右数的位置,然后把1右移右数的个数,比如1<<0得到1,1<<1得到10,1<<2得到100等等,再用来跟data进行&运算,得到某队员的状态,比如对于处于某个状态的data,假设为1110000010,我们来查看'C'的状态,'C'-'A'=2,1<<2=100,然后进行&运算1110000010 & 0000000100(这里注意二进制的位置补齐,高位自动补0),得到结果为0000000000,即结果为0,所以'C'的状态是没参赛,再看'B','B'-'A'=1,1<<1=10,然后进行&运算
    1110000010 & 0000000010,得到结果为0000000010,即不是0,所以'B'的状态为参赛明白了这些,那些至少2人,只能2人的就是判断data的2进制的相应位置的1的个数,这里就不用再解释了
      

  3.   

    阿宝is genius.If I participate this match,I can't think up this way to solve problem. maybe I would use a lot of "if,else",that's too horrible.The answer is too gelivable,thanks
      

  4.   

    楼上的gelivable这个词...我谷歌翻译查不到....
      

  5.   

    我稍微进行了一些优化,只给出思路:
    1. 由条件8,9可以推断出,如果E参加,那么F,G也参加,如果F参加G,H就不能参加可以得出,E是不会参加的。
    2. 然后我们分情况考虑
       a. A参加,则ABCDE=11000(这个根据前4条推断出),好,然后再考虑FGHIJ的参加情况,由于条件6,则G是0(不参加),由条件5,所以F和H必须参加,但这个又和条件9相悖,所以可以断定,A是不参加的。
       b. 由上面的推断结果,A=0,E=0,还是由前4条和第6条,推断出ABCDEG结果有3种情况(000100,010000,011001),说明一下,大家可能对条件3理解不同,如果理解成A和C必须且只能有1个参加的话,那可以肯定ABCDE=011001,且后面的结果直接可以推断出来(应该是这样的,我估计),但是我猜测出题者的意图和条件4的比较,我认为条件3的意思是A和C最多只有1个人参加。
    好,我们再来分开讨论
       1>. ABCDEG=010000,根据条件5,则F,H必须参加,但这又和条件9相悖,PASS
       2>. ABCDEG=000100,考虑FHIJ的情况了
       3>. ABCDEG=011001,根据条件9和5,得出F=0,H=1,根据条件7,得出I=0,最后只需要考虑J的情况了至于上面的分析,已经是我得出的最小化了,代码就不写了,思路出来了,就简单了。 
      

  6.   

    我稍微进行了一些优化,只给出思路:
    1. 由条件8,9可以推断出,如果E参加,那么F,G也参加,如果F参加G,H就不能参加可以得出,E是不会参加的。
    2. 然后我们分情况考虑
      a. A参加,则ABCDE=11000(这个根据前4条推断出),好,然后再考虑FGHIJ的参加情况,由于条件6,则G是0(不参
    ///
    回复15楼,你的分析我怎么有点看不懂,11000代表什么,像这种分析是不是数学上的,如果数学 基础不好,怎么办,,,
      

  7.   

    这道题的答案应该有5个吧,求验证。一、C D G J 
    二、C D G H 
    三、C D G H J 
    四、B C G H 
    五、B C G H J