题目描述
某侦察队接到一项紧急任务,要求在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]
人员 A B C D E F
状态 0 0 0 0 0 0
ABC状态为3种:
数组 a[0] a[1] a[2]
人员 A B C
状态1 1 0 0
状态2 0 1 1
状态3 1 1 1
状态一: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; }
最后可得到正确的输出啦!