【编程题】(满分34分)
某保密单位机要人员 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
网上看到了许多的解法,都感到过于复杂了,试着用位操作的方法来做,效果不错,把源码贴出来分享下
#include<iostream>
#include<string>
using namespace std;
unsigned int m[5] = {118,118,118,118,118};
string change2str(unsigned int n){
unsigned int t=128;
string s="";
char ch;
for(int i=0; i<8; i++,t>>=1)
{
ch = (n&t)>0?'1':'0';
if(i>0)
s.append(1,ch);
}
return s;
}
void leftMoveBit( int index){
unsigned int t=128;
m[index]<<=1;
if((m[index]&t)>0)
{m[index] &=127; m[index]|=1;}
return ;
}
int is1bitPos(int m,int pos){
unsigned int t = 128;
t>>=pos;
return (m&t)>0;
}
int count1bits(int m){
int count=0;
for(int i=1; i<=7; i++){
if(is1bitPos(m, i)) count++;
}
return count;
}
int panDuan(){
//1. 至少有3天所有人都是上班的
unsigned int n = m[0]&m[1]&m[2]&m[3]&m[4];
if(count1bits(n)<3) return 0;
//2.任何一天,必须保证ABCD中至少有2人上班
int count;
for(int day=1; day<=7; day++){
count=0;
for(int i=0; i<4; i++)
if(is1bitPos(m[i],day)) count++;
if(count<2) return 0;
}
//3. B,D,E在周日时必须休息
if(is1bitPos(m[1],7)||is1bitPos(m[3],7)||is1bitPos(m[4],7))
return 0;
//4. A,E必须周三上班
if(!is1bitPos(m[0],3) || !is1bitPos(m[4],3))
return 0;
//5. A C 一周之中至少有四天能够见面
if(count1bits(m[0]&m[2])<4) return 0;
return 1;
}
int main(){
for(int i=0; i<7; i++,leftMoveBit(0))
for(int j=0; j<7; j++, leftMoveBit(1))
for(int k=0; k<7; k++, leftMoveBit(2))
for(int l=0; l<7; l++,leftMoveBit(3))
for(int w=0; w<7; w++, leftMoveBit(4))
if(panDuan())
{
cout<<change2str(m[0])<<endl;
cout<<change2str(m[1])<<endl;
cout<<change2str(m[2])<<endl;
cout<<change2str(m[3])<<endl;
cout<<change2str(m[4])<<endl;
cout<<"-------------------------"<<endl;
}
return 0;
}
运行结果为:
1011011
1110110
1011011
1110110
1110110
-------------------------
0110111
1101110
0110111
1101110
1110110
-------------------------
1011101
1110110
1011101
1110110
1110110
-------------------------
0111011
1110110
0111011
1110110
1110110
-------------------------