资源限制
内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s
问题描述
逗志芃在干了很多事情后终于闲下来了,然后就陷入了深深的无聊中。不过他想到了一个游戏来使他更无聊。他拿出n个木棍,然后选出其中一些粘成一根长的,然后再选一些粘成另一个长的,他想知道在两根一样长的情况下长度最长是多少。
输入格式
第一行一个数n,表示n个棍子。第二行n个数,每个数表示一根棍子的长度。
输出格式
一个数,最大的长度。
样例输入
4
1 2 3 1
样例输出
3
数据规模和约定
n<=15
#include<iostream>
using namespace std;
const int N=15;
int b[1<<N];//若有N个木棍,则有2^N种取法(每个木棍取或不取两种情况)
int main(){
int n;
scanf("%d",&n);
int a[n];
for(int i=n-1;i>=0;i--){
scanf("%d",&a[i]);
}
for(int i=0;i<(1<<n);i++){//共2^n种取法
for(int j=0;j<n;j++){//遍历看看取到的木棍,将取到的木棍长度相加
if(i&(1<<j)){
b[i]+=a[j];
}
}
}
int ans=0;
for(int i=0;i<(1<<n);i++){
for(int j=0;j<(1<<n);j++){
if(!(i&j)&&b[i]==b[j]){//若两种取法没有取到同一个木棍,且两取法得到的木棍总和相等,则得出一个答案
ans=max(ans,b[i]);
}
}
}
printf("%d\n",ans);
return 0;
}
思路:从n个木棍中选木棍,共有种选法(每个木棍选或不选),这
种方法中如果有两种方法没有取到相同的木棍(木棍可以不用全部被取完,只要两种取到的木棍不重合即可),且总长度相等,则为一种答案。最终的答案只是为总长度最大的,用max函数比较一下即可。
若木棍长度数组:1 2 3 1,b[j]表示第j+1种取法,用0表示不取,1表示取。
例:b[1]:0 0 0 1 指的是第2种方法只取了最后的木棍
b[15]:1 1 1 1 指的是第16种取法四个木棍全取
可以用二进制表示这2^4种取法:0000、0001、0010、0011、……、1111,每一种取法通过和0001(判断是不是取第4个)、0010(判断是不是取第3个)、0100、1000按位与得知是否取了第几个木棍。
代码中倒序输入为的就是按位与时判断第几个木棍:
for(int j=0;j<n;j++){//遍历看看取到的木棍,将取到的木棍长度相加
if(i&(1<<j)){
b[i]+=a[j];
}
}
因为是加上a[j],例如j=0时,1<<j=0001,a[j]=a[0],而0001表示取到了第4个木棍而不是a[0]第1个木棍,因此要将a数组逆序输入: (0001判断是不是取第4个,取到则加上原数组的第4个,也可以不用逆序输入,把b[i]+=a[j];改为b[i]+=a[n-j-1]即可)
for(int i=n-1;i>=0;i--){
scanf("%d",&a[i]);
}