标签:
翘了3节课来A这道题,最后还超时了,也是蛮拼的。。
没做出来主要一个方面就是不会一个二进制数子集的枚举
这里上一下代码:
for(int S0 = S; S0; S0 = (S0 - 1) & S){
}这里S0就是S的子集了~!
题目的思路就是枚举所有情况,注意记忆化【话说这题学到了不少】
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
//枚举二叉树的形状
const int maxn = 8;
const int maxd = (1 << 8);
int n;
double ww;
int w[maxn];
int sum[maxd];
int vis[maxd];
double ret;
struct Node{
double l,r;
Node(double ll,double rr):l(ll),r(rr){};
};
vector<Node>node[maxd];
void debug(int v){
if(!v){puts(""); return;}
debug(v / 2);
printf("%d",v % 2);
}
bool judge(int S){
for(int i = 0; i < n; i++)
if(S == (1 << i))
return true;
return false;
}
void dfs(int S){ //枚举now的子集
if(vis[S]) return;
vis[S] = 1;
if(judge(S)){
node[S].push_back(Node(0,0));
return;
}
//printf("%d\n",S);
for(int S0 = S; S0; S0 = (S0 - 1) & S)if(S0 != S){
int l = S0;
int r = S0 ^ S;
dfs(l); dfs(r);
//枚举左右的子集
for(int i = 0; i < node[l].size(); i++)
for(int j = 0; j < node[r].size(); j++){
double l1 = 1.0 * sum[r] / (sum[l] + sum[r]);
double r1 = 1.0 * sum[l] / (sum[l] + sum[r]);
double l2 = min(-l1 + node[l][i].l,r1 + node[r][j].l);
double r2 = max(-l1 + node[l][i].r,r1 + node[r][j].r);
//printf("[%d]: %.2f %.2f\n",S,l2,r2);
node[S].push_back(Node(l2,r2));
}
}
return;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%lf%d",&ww,&n);
ret = -1;
memset(vis,0,sizeof(vis));
for(int i = 0; i < n; i++)
scanf("%d",&w[i]);
for(int i = 0; i < (1 << n); i++){
sum[i] = 0;
node[i].clear();
for(int j = 0;j < n; j++){
if(i & (1 << j)){
sum[i] += w[j];
}
}
}
int S = (1 << n) - 1;
dfs(S);
//printf("%d\n",node[S].size());
for(int i = 0; i < node[S].size(); i++){
double d = node[S][i].r - node[S][i].l;
//printf("%.4f %.4f\n",node[S][i].r,node[S][i].l);
if(d <= ww)
ret = max(ret,d);
}
if(ret < 0) printf("-1\n");
else
printf("%.16f\n",ret);
}
return 0;
}
1354 Mobile Computing(暴力、二进制枚举、简直无情)
标签:
原文地址:http://blog.csdn.net/u013451221/article/details/44308003