某保密单位机要人员 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行记录,从星期一开始。

【输入、输出格式要求】

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

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

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

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

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

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

0110111

1101110

0110111

1101110

1110110

思路:

这个题目我选了一个较为简单的做法,首相所有出现符合的工作日求出,然后进行排列组合,用条件一一排除即可。

【注意】

请仔细调试!您的程序只有能运行出正确结果的时候才有机会得分!

在评卷时使用的输入数据与试卷中给出的实例数据可能是不同的。

a[i][j]表示第i个人在星期j是否工作,1为工作,0为休息。

一道真的很麻烦的题目,需要认真跟着条件写代码。第三个条件任何一天,必须保证 A B C D 中至少有2人上班。

应该写成

int f3()// 任何一天,必须保证 A B C D 中至少有2人上班。
{
for(int j=1;j<=7;j++)
{
if(a[1][j]+a[2][j]+a[3][j]+a[4][j]<2)
return 0;
}
return 1;
}

后面的写法是错误的,这里没注意,困扰了挺久。这种实际上为存在任何一天,满足条件。

应注意逻辑关系。

int f3()// 任何一天,必须保证 A B C D 中至少有2人上班。
{
for(int j=1;j<=7;j++)
{
if(a[1][j]+a[2][j]+a[3][j]+a[4][j]>=2)
return 1;
}
return 0;
}

完整代码:

#include <stdio.h>
using namespace std;
int a[8][8];
int f1()//所有人的连续工作日不能多于3天
{
for(int i=1;i<6;i++)
{
for(int j=1;j<=7;j++)
{
int t1=(j+1)%7;
int t2=(j+2)%7;
int t3=(j+3)%7;
if(t1==0)
t1=7;
if(t2==0)
t2=7;
if(t3==0)
t3=7;
if(a[i][j]+a[i][t1]+a[i][t2]+a[i][t3]==4)
return 0;
}
}
}
int f2()//一周中,至少有3天所有人都是上班的。
{
int sum=0;
for(int j=1;j<=7;j++)
{
int cnt=0;
for(int i=1;i<6;i++)
{
if(a[i][j]==1)
cnt++;
}
if(cnt==5)
sum++;
}
if(sum>=3)
return 1;
else
return 0;
}
int f3()// 任何一天,必须保证 A B C D 中至少有2人上班。
{
for(int j=1;j<=7;j++)
{
if(a[1][j]+a[2][j]+a[3][j]+a[4][j]<2)
return 0;
}
return 1;
}
int f4()// B D E 在周日那天必须休息。
{
if(a[2][7]+a[4][7]+a[5][7]==0)
return 1;
return 0;
}
int f5()//A E 周三必须上班。
{
if(a[1][3]+a[5][3]==2)
return 1;
return 0;
}
int f6()//A C 一周中必须至少有4天能见面(即同时上班)。
{
int cnt=0;
for(int j=1;j<=7;j++)
{
if(a[1][j]+a[3][j]==2)
cnt++;
}
if(cnt>=4)
return 1;
return 0;
}
void dfs(int now)
{
if(now==6)//当所有人的日期都被决定
{
if(f1()&&f2()&&f3()&&f4()&&f5()&&f6())//判断条件
{
for(int i=1;i<6;i++)
{
for(int j=1;j<=7;j++)
printf("%d",a[i][j]);
printf("\n");
}
printf("\n");
}
return;
}
for(int i=1;i<=7;i++)//穷举休息日
{
for(int j=i+1;j<=7;j++)
{
a[now][i]=0;
a[now][j]=0;
dfs(now+1);
a[now][i]=1;
a[now][j]=1;
}
}
}
int main()
{
for(int i=1;i<=6;i++)//初始所有人每天都上班
{
for(int j=1;j<=7;j++)
{
a[i][j]=1;
}
}
dfs(1);
return 0;
}

蓝桥杯——排日期_f5