某保密单位机要人员 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循环语句过多而混乱,这样便于表达思路)。
最后,就是对题目中的条件的表达,从代码中可以看到,并不是把每个条件的所有实现都写在了一起,而是复杂的又进行了割裂,这样虽然多写了几行代码,但是一个一个模块的实现、组合,让思路更加的清晰,保证了程序的可读性,以及后续代码的稳定编写!