题目描述如下:

ABCDE五人安排工作日程,每人每星期工作5天休息2

1)        必须有3天所有人都要上班

2)        每个人连续上班不超过3天,周日到周一是连续工作

3)        AC星期三必须上班

4)        BDE星期天都不上班

5)        AC一星期至少见4

6)        ABCD中每天必须至少有2人上班

输出所有从星期一到星期天可能的情况,每种情况间用空行隔开,0代表不上班,1代表上班。

例:

1 0 1 1 1 0 1

1 1 0 1 1 1 0

1 0 1 1 1 0 1

1 1 0 1 1 1 0

1 1 0 1 1 1 0

 

结题思路:

题目的每个解是一个5*701矩阵,枚举每一个矩阵,然后用题目所给的条件判定即可,时间复杂度为O(2^35),明显超时。结合题目条件“每人每星期工作5天休息2”,我们可以完成初步剪枝:对每个人的工作表,可以看成在五个1中插入两个00的具体位置可以看成一个组合问题,既是在6个位置中选择两个位置(这里已经排除两个0相邻的情况,因为条件2)。这样,题目的复杂度为O((C26)^5),相当小啦。除了条件1,其余的条件判断均可在排列过程中进行,作为剪枝只用。

 

 代码如下:

 


public class Main {
    
    
    
static int mp[][] = new int[5][7];
    
static int count;
    
static int num[][] = {
        
{012345},
        
{012345},
        
{012345},
        
{012345},
        
{012345}    
        
/*
         * 每个员工使用num[][]的一行完成组合,
         * 避免别的员工组合计算时的残留值
         
*/

    }
;
    
public static void main(String[] args) {
        count 
= 0;
        DFS(
000);
        System.out.println(
"count=" + count);
        
for(int i = 0; i < num.length; i++){
            
for(int n : num[i])
                System.out.print(n 
+ " ");
            System.out.print(
"\n");
        }

        
    }

    
static void outmp(){
        System.out.println();
        
for(int i = 0; i < 5; i++){
            
for(int j = 0; j < 7; j++)
                System.out.print(mp[i][j] 
+ " ");
            System.out.println();
        }

    }

    
static void DFS(int c, int nowp, int left){
        
/*
         * c,当前员工(0,1,2,3,4)
         * nowp,left用于计算组合
         
*/

        
if(c >= 5){
            
if(R1()){
                outmp();
                count
++;
            }

            
return;
        }

        
if(nowp == 2){
            makemp(c, num[c][
0], num[c][1]);
            
if(!R2(c))//R2
                return;
            
if(c == 0 && mp[0][2!= 1)//R3
                return;
            
if(c == 2 && mp[2][2!= 1)
                
return;
            
if(c == 1 && mp[1][6!= 0)//R4
                return;
            
if(c == 3 && mp[3][6!= 0)
                
return;
            
if(c == 4 && mp[4][6!= 0)
                
return;
            
if(c == 2 && !R5())//R5
                return;
            
if(c == 3 && !R6())//R6
                return;
            
            DFS(c 
+ 100);
        }

        
else{
            
for(int i = left; i < num[0].length; i++){
                swap(num[c], nowp, i);
                DFS(c, nowp 
+ 1, i + 1);
                swap(num[c], nowp, i);
            }

        }

    }

    
static void makemp(int c, int a, int b){
        
for(int i = 0; i < a; i++)
            mp[c][i] 
= 1;
        mp[c][a] 
= 0;
        
for(int i = a + 1; i <= b; i++)
            mp[c][i] 
= 1;
        mp[c][b 
+ 1= 0;
        
for(int i = b + 2; i < 7; i++)
            mp[c][i] 
= 1;
    }

    
static boolean R1(){
        
int count = 0
        
for(int i = 0; i < 7; i++){
            
if(chechRol(i))
                count
++;
        }

        
if(count >= 3)
            
return true;
        
return false;
    }

    
static boolean chechRol(int r){
        
for(int i = 0; i < 5; i++)
            
if(mp[i][r] != 1)
                
return false;
        
return true;
    }

    
static boolean R2(int c){//one person
        int count = 0;
        
boolean bg = false;
        
for(int i = 0; i < 7; i++){
            
if(mp[c][i] != 0){
                
if(bg == false){
                    count 
= 1;
                    bg 
= true;
                }

                
else{
                    count
++;
                    
if(count > 3)
                        
return false;
                }

            }

            
else{
                bg 
= false;
            }

        }

        
return true;
    }

    
static boolean R5(){
        
int count = 0;
        
for(int i = 0; i < 7; i++){
            
if(mp[0][i] == 1 && mp[2][i] == 1)
                count
++;
        }

        
if(count >= 4)
            
return true;
        
return false;
    }

    
static boolean R6(){
        
int count = 0;
        
for(int i = 0; i < 7; i++){
            count 
= 0;
            
for(int j = 0; j < 5; j++)
                
if(mp[j][i] == 1)
                    count
++;
            
if(count < 2)
                
return false;
        }

        
return true;
    }

    
static void swap(int a[], int n, int m){
        
int t = a[n];
        a[n] 
= a[m];
        a[m] 
= t;
    }

}

 

posted on 2013-07-06 15:43 小鼠标 阅读(179) 评论(0)  编辑 收藏 引用 所属分类: Java基础练习

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2013年7月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

常用链接

随笔分类(111)

随笔档案(127)

friends

最新评论

  • 1. re: 线段树
  • 是这个样子的,所以在OJ有时候“卡住”了也不要太灰心,没准真的不是自己的原因呢。
    加油,祝你好运啦!
  • --小鼠标
  • 2. re: 线段树
  • 对于编程竞赛来说,Java所需时间一般为C/C++的两倍。合理的竞赛给Java的时间限制是给C/C++的两倍。
  • --伤心的笔
  • 3. re: poj1273--网络流
  • 过来看看你。
  • --achiberx
  • 4. re: (转)ubuntu11.10无法启动无线网络的解决方法
  • 膜拜大神。。查了一个下午资料终于在这里解决了问题。。神牛说的区域赛难道是ACM区域赛。。?
  • --Hang
  • 5. re: 快速排序、线性时间选择
  • 博主,谢谢你的文章。你的方法可以很好的处理分区基准在数组中重复的情况,书上的方法遇到这种输入会堆栈溢出。书上给出了解释但给的方法貌似不简洁。
  • --lsxqw2004

阅读排行榜