每天一道C语言编程(6):委派任务

题目描述

某侦察队接到一项紧急任务,要求在A、B、C、D、E、F六个队员中尽可能多地挑若干人,但有以下限制条件:
1)A和B两人中至少去一人;
2)A和D不能一起去;
3)A、E和F三人中要派两人去;
4)B和C都去或都不去;
5)C和D两人中去一个;
6)若D不去,则E也不去。
问应当让哪几个人去?

输出格式

要派出的人
若有多个,按字母递增顺序排列,用逗号分开(含末尾逗号)

样例输出

A,B,C,F,

思路

根据以下条件,可列出表格:
1A和B两人中至少去一人;
2A和D不能一起去;
3A、E和F三人中要派两人去;
4B和C都去或都不去;
5C和D两人中去一个;
6若D不去,则E也不去。

条件一条件二条件三条件四条件五条件六
A去B不去A去D不去AE去F不去BC都去C去D不去DE都不去
A不去B去A不去D去AF去E不去BC都不去C不去D去DE都去
AB都去AD都不去EF去A不去D去E不去

容易得出A,B,C之间的关系为:

1.A去,B,C都不去

2.A不去,B,,C都去

3.A,B,C都去

if(状态1||状态2||状态3){
    //其他限制条件,继续筛选
}

这样一来,本来6个人,每人两种状态有2的6次方:64种状态,现在变为

以或(||)为连接,A,B,C三人每人有两种状态,2^3+2^3+2^3,即3*2^3=24种

现在只有2,3,5,6四种限制了,即:

if(条件二&&条件三&&条件五&&条件六){
    if(是最优解){
        输出此时状态为去的人
    }
}

代码显示

1. 声明一个数组a[10],用a[0]的值来表示人员A的状态——若a[0]为‘0’代表A不去,a[0]为‘1’代表A去;
同理a[1]代表B的状态、a[2]代表C、a[3]代表D、a[4]代表E、a[6]代表F;
初始化数组a[10]中的元素全为0,即所有人的状态均为不去

数组a[0]a[1]a[2]a[3]a[4]a[5]
人员ABCDEF
状态000000

ABC状态为3种:

数组a[0]a[1]a[2]
人员ABC
状态1100
状态2011
状态3111

 状态一:a[0]+a[1]+a[2]=1,状态二:a[0]+a[1]+a[2]=2,状态三:a[0]+a[1]+a[2]=3

for(i=1;i<4;i++){
    if(i==1){
        //A、B、C的值为状态1时的值1、0、0
        a[0]=1;
        a[1]=0;//由于初始化数组元素全为0,这里a[1]和a[2]的赋值也可以省去
        a[2]=0;
    }
    if(i==2){
        //A、B、C的值为状态2时的值0、1、1
    }
    if(i==3){
        //A、B、C的值为状态3时的值1、1、1
    }
    //其他限制条件
}

现在只需要对D,E,F的两种状态进行遍历:

for(i=1;i<4;i++){
    if(i==1){
        //A、B、C的值为状态1时的值1、0、0
        a[0]=1;
        a[1]=0;//由于初始化数组元素全为0,这里a[1]和a[2]的赋值也可以省去
        a[2]=0;
    }
    if(i==2){
        a[0]=0;
        a[1]=1;
        a[2]=1;
    }
    if(i==3){
        a[0]=1;
        a[1]=1;
        a[2]=1;
    }
    for(a[3]=0;a[3]<2;a[3]++){//D的两种状态
        for(a[4]=0;a[4]<2;a[4]++){//E的两种状态
            for(a[5]=0;a[5]<2;a[5]++){//F的两种状态
                if(条件2&&条件3&&条件5&&条件6){
                    if(最优解){
                        //输出即可
                    }
                }
            }
        }
    }
}

得到24种状态分别为:

#include<stdio.h>
int main(void){
    int a[10]={0};
    int b[10]={0};
    int i,j;
    int mark=1;
    for(i=1;i<4;i++){//根据第一个和第四个条件可得,A、B、C的可能组合有三种 
        if(i==1){
            a[0] = 1;
        }else if(i==2){
            a[0] = 0;
            a[1] = 1;
            a[2] = 1;
        }else{
            a[0] = 1;
            a[1] = 1;
            a[2] = 1;
        }
        for(a[3]=0;a[3]<2;a[3]++){
            for(a[4]=0;a[4]<2;a[4]++){
                for(a[5]=0;a[5]<2;a[5]++){
                    printf("第%2d种:",mark);
                    for(j=0;j<6;j++){
                        printf("%d ",a[j]);
                    }
                    mark++;
                    printf("\n");
                 } 
              }
          }
      }
return 0;
}
   

得: 

 接下来是限制条件二,三,五,六:

条件二条件三条件五条件六
A去D不去AE去F不去C去D不去DE都不去
A不去D去AF去E不去C不去D去DE都去
AD都不去EF去A不去D去E不去

条件二:((a[0]==1&&a[3]==0)||(a[0]==0&&a[3]==1)||(a[0]==0&&a[3]==0))
条件三:((a[0]==1&&a[4]==1&&a[5]==0)||(a[0]==1&&a[4]==0&&a[5]==1)||(a[0]==0&&a[4]==1&&a[5]==1))
条件五:((a[2]==1&&a[3]==0)||(a[2]==0&&a[3]==1))
条件六:((a[3]==0&&a[4]==0)||(a[3]==1&&a[4]==0)||(a[3]==1&&a[4]==1)))

 在比较哪一种条件下sum最多:

//求得最优解
for(j=0;j<6;j++){
    sum1 += a[j];
}
if(sum1>sum2){//筛选人数最多的解 
    sum2 = sum1;
    for(j=0;j<6;j++){
        b[j] = a[j];
    }
}

最后得到代码为:
 

#include<stdio.h>
int main(void){
    int a[10]={0};
    int b[10]={0};
    int i,j,sum1,sum2;
    sum1=sum2=0;
    //int mark=1;
    for(i=1;i<4;i++){//根据第一个和第四个条件可得,A、B、C的可能组合有三种 
        if(i==1){
            a[0] = 1;
        }else if(i==2){
            a[0] = 0;
            a[1] = 1;
            a[2] = 1;
        }else{
            a[0] = 1;
            a[1] = 1;
            a[2] = 1;
        }
        for(a[3]=0;a[3]<2;a[3]++){
            for(a[4]=0;a[4]<2;a[4]++){
                for(a[5]=0;a[5]<2;a[5]++){
                    /*
                    printf("第%2d种:",mark);
                    for(j=0;j<6;j++){
                        printf("%d ",a[j]);
                    }
                    mark++;
                    printf("\n"); 
                    */
                    if(((a[0]==1&&a[3]==0)||(a[0]==0&&a[3]==1)||(a[0]==0&&a[3]==0))&&
                    ((a[0]==1&&a[4]==1&&a[5]==0)||(a[0]==1&&a[4]==0&&a[5]==1)||(a[0]==0&&a[4]==1&&a[5]==1))&&
                    ((a[2]==1&&a[3]==0)||(a[2]==0&&a[3]==1))&&
                    ((a[3]==0&&a[4]==0)||(a[3]==1&&a[4]==0)||(a[3]==1&&a[4]==1))){
                        for(j=0;j<6;j++){
                            sum1 += a[j];
                        }
                        if(sum1>sum2){//筛选人数最多的解 
                            sum2 = sum1;
                            //printf("符合条件的组合:"); 
                            for(j=0;j<6;j++){
                                b[j] = a[j];
                                //printf("%d ",b[j]);
                            }
                            //printf("\n");
                        }
                    }
                }
            }
        }
    }
    if(b[0]==1){
        printf("A,");
    }
    if(b[1]==1){
        printf("B,");
    }
    if(b[2]==1){
        printf("C,");
    }
    if(b[3]==1){
        printf("D,");
    }
    if(b[4]==1){
        printf("E,");
    }
    if(b[5]==1){
        printf("F,");
    }
    return 0;
}

最后可得到正确的输出啦!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值