题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4152
/*
4
100 200 300 400
3
100 100 400 500
100 -10 50 300
100 100 -50 -50
*/
#include
int goal[30];
int f[25][25],g[30];
main(){
int i,j,n,m,ans1,ans2;
while(scanf("%d",&n)!=EOF){
ans1=-1;
for(i=0;i<n;i++)
scanf("%d",&goal[i]);
scanf("%d",&m);
for(i=0;i<m;i++)
for(j=0;j<n;j++)
scanf("%d",&f[i][j]);
for(i=0;i<(1<<m);i++){
for(j=0;j<n;j++)
g[j]=0;
int num=0,k;
for(j=0;j<m;j++)
if(i&(1<<j)){
num++;
for(k=0;k<n;k++)
g[k]+=f[j][k];
}
int p;
for(p=0;p<n;p++)
if(g[p]=n){
if(num>ans1)ans1=num,ans2=i;
else if(num==ans1&&ans2>i)
ans1=num,ans2=i;
}
}
if(ans1==-1)printf("0\n");
else{
printf("%d",ans1);
for(i=0;i<n;i++)
if(ans2&(1<<i))
printf(" %d",i+1);
printf("\n");
}
}
}
这段代码可以清楚地理解二进制枚举究竟是怎样的
#include<stdio.h>
int goal[30];
int f[25][25],g[30];
main(){
int n,i,j,k,m,ans1,ans2;
scanf("%d",&m);
for(i=1;i<(1<<m);i++){
printf("%d ",i);
int num=0;
for(j=0;j<m;j++){
if(i&(1<<j)){//i==2^j
printf("%d ",j);
else
printf("* ");
printf("\n");
}
}
int goal[30];
int f[25][25],g[30];
main(){
int n,i,j,k,m,ans1,ans2;
scanf("%d",&m);
for(i=1;i<(1<<m);i++){
printf("%d ",i);
int num=0;
for(j=0;j<m;j++){
if(i&(1<<j)){//i==2^j
printf("%d ",j);
else
printf("* ");
printf("\n");
}
}
计蒜客的题目(换成最少习惯,没说全吃掉也不满足的情况,所以不知道第六组测试点怎么过)
题目地址:https://nanti.jisuanke.com/t/41
#include
int goal[40];
int f[40][40],g[40];
main(){
int i,j,n,m,ans1,ans2;
// while(scanf("%d",&n)!=EOF){
scanf("%d",&n);
ans1=99999999;
for(i=0;i<n;i++)
scanf("%d",&goal[i]);
scanf("%d",&m);
for(i=0;i<m;i++)
for(j=0;j<n;j++)
scanf("%d",&f[i][j]);
for(i=1;i<(1<<m);i++){
for(j=0;j<n;j++)
g[j]=0;
int num=0,k;
for(j=0;j<m;j++)
if(i&(1<<j)){
num++;
for(k=0;k<n;k++)
g[k]+=f[j][k];
}
int p;
for(p=0;p<n;p++)
if(g[p]=n){ //不是废话,说明前面遍历过了,达到目标了
if(num<ans1)ans1=num,ans2=i;//改成<,就是找最小的,而且i从1开始,j那层循环不会有和它匹配不上的,也就是说,一定会有num++
else if(num==ans1&&ans2>i) //习惯数相同,输出靠前的
ans2=i;
}
}
if(ans1==99999999){
printf("%d",n);
for(i=0;i<n;i++)
printf(" %d",i+1);
}
else{
printf("%d",ans1);
for(i=0;i<n;i++)
if(ans2&(1<<i))
printf(" %d",i+1);
printf("\n");
}
//}
}