穷举——排日期

某保密单位机要人员 A,B,C,D,E 每周需要工作5天,休息2天。

上级要求每个人每周的工作日和休息日安排必须是固定的,不能在周间变更。

此外,由于工作需要,还有如下要求:

1. 所有人的连续工作日不能多于3天(注意:周日连到下周一也是连续)。

2. 一周中,至少有3天所有人都是上班的。

3. 任何一天,必须保证 A B C D 中至少有2人上班。

4. B D E 在周日那天必须休息。

5. A E 周三必须上班。

6. A C 一周中必须至少有4天能见面(即同时上班)。

你的任务是:编写程序,列出ABCDE所有可能的一周排班情况。工作日记为1,休息日记为0

A B C D E 每人占用1行记录,从星期一开始。

【输入、输出格式要求】

程序没有输入,要求输出所有可能的方案。

每个方案是5*7的矩阵。只有1和0组成。        

矩阵中的列表示星期几,从星期一开始。

矩阵的行分别表示A,B,C,D,E的作息时间表。

多个矩阵间用空行分隔开。

例如,如下的矩阵就是一个合格的解。请编程输出所有解(多个解的前后顺序不重要)。

0110111
1101110
0110111
1101110
1110110


public class Main {

    public static int[][] table = {
        {0,0,1,0,0,0,1},
        {0,0,0,0,0,0,0},
        {0,0,0,0,0,0,1},
        {0,0,0,0,0,0,0},
        {1,1,1,0,1,1,0}
    };

    //每周需要工作5天,休息2天。
    public static boolean fun0(){
        for(int i=0;i<5;i++){
            int cnt = 0;
            for(int j=0;j<7;j++){
                if(table[i][j]==1) ++cnt;
            }
            if(cnt!=5) return false;
        }
        return true;
    }

    //1. 所有人的连续工作日不能多于3天(注意:周日连到下周一也是连续)。
    public static boolean isLonger(int i){//统计第i个人的工作情况
        for(int j=0;j<7;j++){
            int cnt = 0;
            for(int k=0;k<4;k++){
                int v = (j+k)%7;
                if(table[i][v]==1){
                    ++cnt;
                }
            }
            if(cnt==4) return true;
        }
        return false;
    }
    public static boolean fun1(){
        for(int i=0;i<5;i++){
            if(isLonger(i)) return false;
        }
        return true;
    }

    //2. 一周中,至少有3天所有人都是上班的。
    public static boolean isFull(int j){//判断第j天是否所有人都上班
        for(int i=0;i<5;i++){
            if(table[i][j]!=1) return false;
        }
        return true;
    }
    public static boolean fun2(){
        int cnt = 0;
        for(int j=0;j<7;j++){
            if (isFull(j)) ++cnt;
        }
        if(cnt>=3) return true;
        return false;
    }

    //3. 任何一天,必须保证 A B C D 中至少有2人上班。
    public static boolean isABCD(int j){//判定在第j天是否A B C D 中至少有2人上班。
        int cnt = 0;
        for(int i=0;i<4;i++){
            if(table[i][j]==1) cnt++;
        }
        if(cnt>=2) return true;
        return false;
    }
    public static boolean fun3() {
        for(int j=0;j<7;j++){
            if(!isABCD(j)) return false;
        }
        return true;
    }

    //4. B D E 在周日那天必须休息。
    public static boolean fun4() {
        if(table[1][6]==0&&table[3][6]==0&&table[4][6]==0) return true;
        return false;
    }

    // 5. A E 周三必须上班。
    public static boolean fun5() {
        if(table[0][2]==1&&table[4][2]==1) return true;
        return false;
    }
   // 6. A C 一周中必须至少有4天能见面(即同时上班)。

    public static boolean fun6() {
        int cnt = 0;
        for(int j=0;j<7;j++){
            if(table[0][j]==1&&table[2][j]==1) ++cnt;
        }
        if(cnt>=4) return true;
        return false;
    }

    public static void show(){
        //System.out.println("Output table:");
        for(int i=0;i<5;i++){
            for(int j=0;j<7;j++) System.out.print(table[i][j]);
            System.out.println();
        }
        System.out.println();
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        //要把表全部构建起来才能进行判定,现在关键在于如何罗列出表的所有情况
        //按从层次进行分解,穷举
        for(table[0][0]=0;table[0][0]<2;table[0][0]++)
        for(table[0][1]=0;table[0][1]<2;table[0][1]++)  
        for(table[0][2]=0;table[0][2]<2;table[0][2]++)
        for(table[0][3]=0;table[0][3]<2;table[0][3]++)
        for(table[0][4]=0;table[0][4]<2;table[0][4]++)  
        for(table[0][5]=0;table[0][5]<2;table[0][5]++)
        for(table[0][6]=0;table[0][6]<2;table[0][6]++)

        for(table[1][0]=0;table[1][0]<2;table[1][0]++)
        for(table[1][1]=0;table[1][1]<2;table[1][1]++)  
        for(table[1][2]=0;table[1][2]<2;table[1][2]++)
        for(table[1][3]=0;table[1][3]<2;table[1][3]++)
        for(table[1][4]=0;table[1][4]<2;table[1][4]++)  
        for(table[1][5]=0;table[1][5]<2;table[1][5]++)
        for(table[1][6]=0;table[1][6]<2;table[1][6]++)  

        for(table[2][0]=0;table[2][0]<2;table[2][0]++)
        for(table[2][1]=0;table[2][1]<2;table[2][1]++)  
        for(table[2][2]=0;table[2][2]<2;table[2][2]++)
        for(table[2][3]=0;table[2][3]<2;table[2][3]++)
        for(table[2][4]=0;table[2][4]<2;table[2][4]++)  
        for(table[2][5]=0;table[2][5]<2;table[2][5]++)
        for(table[2][6]=0;table[2][6]<2;table[2][6]++)  

        for(table[3][0]=0;table[3][0]<2;table[3][0]++)
        for(table[3][1]=0;table[3][1]<2;table[3][1]++)  
        for(table[3][2]=0;table[3][2]<2;table[3][2]++)
        for(table[3][3]=0;table[3][3]<2;table[3][3]++)
        for(table[3][4]=0;table[3][4]<2;table[3][4]++)  
        for(table[3][5]=0;table[3][5]<2;table[3][5]++)
        for(table[3][6]=0;table[3][6]<2;table[3][6]++)
        {
                     if(fun0()&&fun1()&&fun2()&&fun3()&&fun4()&&fun5()&&fun6()) show();
        }
    }

}

首先,拿到这道题时应先根据题意列出初始A,B , C , D , E 状态,然后再根据条件:所有人的连续工作日不能多于3天(注意:周日连到下周一也是连续)以及工作5天,休息两天,即可得E的工作表情况:1110110。
然后,需要对除E以为表中的每个单元进行穷举,以人为第一单位,以日期为第二单位(穷举时往往会由于,for循环语句过多而混乱,这样便于表达思路)。
最后,就是对题目中的条件的表达,从代码中可以看到,并不是把每个条件的所有实现都写在了一起,而是复杂的又进行了割裂,这样虽然多写了几行代码,但是一个一个模块的实现、组合,让思路更加的清晰,保证了程序的可读性,以及后续代码的稳定编写!

CH341A编程器是一款广泛应用的通用编程设备,尤其在电子工程和嵌入式系统开发领域中,它被用来烧录各种类型的微控制器、存储器和其他IC芯片。这款编程器的最新版本为1.3,它的一个显著特点是增加了对25Q256等32M芯片的支持。 25Q256是一种串行EEPROM(电可擦可编程只读存储器)芯片,通常用于存储程序代码、配置数据或其他非易失性信息。32M在这里指的是存储容量,即该芯片可以存储32兆位(Mbit)的数据,换算成字节数就是4MB。这种大容量的存储器在许多嵌入式系统中都有应用,例如汽车电子、工业控制、消费电子设备等。 CH341A编程器的1.3版更新,意味着它可以与更多的芯片型号兼容,特别是针对32M容量的芯片进行了优化,提高了编程效率和稳定性。26系列芯片通常指的是Microchip公司的25系列SPI(串行外围接口)EEPROM产品线,这些芯片广泛应用于各种需要小体积、低功耗和非易失性存储的应用场景。 全功能版的CH341A编程器不仅支持25Q256,还支持其他大容量芯片,这意味着它具有广泛的兼容性,能够满足不同项目的需求。这包括但不限于微控制器、EPROM、EEPROM、闪存、逻辑门电路等多种类型芯片的编程。 使用CH341A编程器进行编程操作时,首先需要将设备通过USB连接到计算机,然后安装相应的驱动程序和编程软件。在本例中,压缩包中的"CH341A_1.30"很可能是编程软件的安装程序。安装后,用户可以通过软件界面选择需要编程的芯片类型,加载待烧录的固件或数据,然后执行编程操作。编程过程中需要注意的是,确保正确设置芯片的电压、时钟频率等参数,以防止损坏芯片。 CH341A编程器1.3版是面向电子爱好者和专业工程师的一款实用工具,其强大的兼容性和易用性使其在众多编程器中脱颖而出。对于需要处理25Q256等32M芯片的项目,或者26系列芯片的编程工作,CH341A编程器是理想的选择。通过持续的软件更新和升级,它保持了与现代电子技术同步,确保用户能方便地对各种芯片进行编程和调试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值