试题 历届真题 排日程表【第三届】【决赛】【高职组】

试题 历届真题 排日程表【第三届】【决赛】【高职组】

题解

在这里插入图片描述
在这里插入图片描述


好没把握。我好难过
自己一开始的思路是很有很有问题的。一开始是设置一个5*7的矩阵,每个位置穷举0 1,这样就有235 = 34,359,738,368 种可能。铁定算不出来。

然后自己后来又想到状态压缩,可是还是需要穷举,自己也还是不会了

归根结底在于自己想不出来好的方法穷举。

怪自己 动手能力太差,生活经验缺少,联系实际的能力很差。

对于a[i][j]表示i在周j上班:则a[i][j]只有两天休息,其他5天上班。
在这里插入图片描述

所以要做的是穷举休息日,两天即可。咋枚举?你根本不会

先枚举第一天 ,然后第二天要在第一天后面否则就会有重复。

但是这里需要初始化每个a[i][j]都为1 这样再去穷举那两个是0。

for(int i=1;i<=7;i++)	枚举休息日第一天
{
	for(int j=i+1;j<=7;j++)	枚举休息日第二天
	a[who][i] = 0;
	a[who][j] = 0;
	dfs(who);
	a[who][i] = 1;
	a[who][j] = 1;

6个条件 讲道理 我也有的不会。

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N  = 10;
int a[N][N];    //a[i][j]表示i在周j工作
bool f1() //所有人连续工作日不能多于3天
{
    //因为所有人的连续工作日不能超过3天,那就穷举四天 如果有干四天的情况 返回假,
    for(int i=1;i<=5;i++)
        for(int j=1;j<=7;j++)
        {
            int t1,t2,t3; 
            t1 = (j+1)%7;
            t2 = (j+2)%7;
            t3 = (j+3)%7;
            if(t1==0) t1=7; // 注意整除的情况 如果整除说明正好在周日 但是取余的结果是0
            if(t2==0) t2=7;
            if(t3==0) t3=7;
            if(a[i][j] + a[i][t1]+a[i][t2]+a[i][t3]==4) // 如果有干4天的情况
                return false;
        }
    return true;
}

bool f2()
{
    int sum = 0;
    int res = 0;
    for(int j=1;j<=7;j++)
    {
        sum = 0;
        for(int i=1;i<=5;i++)
        {
            sum += a[i][j];
        }
        if(sum == 5 ) res ++;   //工作5天不是7天!
    }
    return res >= 3 ;
}
bool f3()
{
    for(int i=1;i<=7;i++)
    {
        if(a[1][i] + a[2][i] + a[3][i] + a[4][i] < 2)
            return false;
    }
    return true;
}
bool f4()
{
    if(a[2][7]==0 && a[4][7]==0 && a[5][7] == 0) return true;
    return false;
}
bool f5()
{
    if(a[1][3] + a[5][3]==2) return true;
    return false;
}
bool f6()
{
    int res = 0;
    for(int i=1;i<=7;i++)
    {
        if(a[1][i] + a[3][i] == 2) res++;
    }
    return res >=4;
}
void dfs(int who)
{
    if(who == 6) //出口
    {
        if(f1() && f2() && f3() && f4() && f5() && f6())
        {
            for(int i=1;i<=5;i++)
            {
                for(int j=1;j<=7;j++)
                    printf("%d",a[i][j]);
                puts("");
            }
            puts("");
        }
        return;
    }
    
    //枚举休息日 连续的两天
    for(int i=1;i<=7;i++)
    {
        for(int j=i+1;j<=7;j++)
        {
            a[who][i] = 0;
            a[who][j] = 0;
            dfs(who+1);
            a[who][i] = 1;
            a[who][j] = 1;
        }

    }
}
int main()
{
    //全部初始化为1 然后枚举找休息日
    for(int i=1;i<=6;i++)
        for(int j=1;j<=7;j++)
            a[i][j] = 1;
    dfs(1);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值