您的位置:首页 > 其它

poj 3900 dfs搜索剪枝+后缀和预处理+贪心

2018-02-21 15:24 337 查看
点击打开链接


//dfs搜索剪枝+后缀和预处理
//首先利用性价比贪心,单位质量的价值越高则性价比越高
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long LL;
int n;
LL m,ans; //m为总重量,ans为最优解
LL sum[200];
struct maze{
LL weight,value;
double pos;
int num; //钻石数量
};
maze field[200];
bool cmp(maze a,maze b)
{
return a.pos>b.pos;
}
void dfs(int x,LL now_value,LL now_weight)
{
ans=max(ans,now_value); //更新最优解
if(now_weight<=0||x>n) return;
if(now_value+sum[x]<=ans) return; //如果当前的价值加上其余钻石的所有价值<=ans,则剪枝
double best=field[x].pos;
if(now_value+(LL)ceil(now_weight*best)<=ans) return; //剩下的重量全部装性价比最高的钻石,如果得到的价值小于此时已经得到的价值,则剪枝
for(int i=field[x].num;i>=0;i--) //先选择性价比较高的箱子
{
if(now_weight<field[x].weight*i) continue;
dfs(x+1,now_value+field[x].value*i,now_weight-field[x].weight*i);
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
ans=0;
scanf("%d%lld",&n,&m);
LL sumw=0,sumv=0;
for(int i=1;i<=n;i++)
{
LL w;
scanf("%lld",&w);
sumw+=(LL)i*w;
field[i].weight=w;
field[i].num=i;
}
for(int i=1;i<=n;i++)
{
LL v;
scanf("%lld",&v);
sumv+=(LL)v*i;
field[i].value=v;
field[i].pos=(double)field[i].value/field[i].weight;
}
if(sumw<=m) {
cout<<sumv<<endl;
continue;
}
//求后缀和
sort(field+1,field+n+1,cmp); //按照性价比排序
memset(sum,0,sizeof(sum));
for(int i=n;i>=1;i--)
sum[i]=sum[i+1]+field[i].value*field[i].num;
dfs(1,0,m);
cout<<ans<<endl;
}
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  剪枝 dfs poj 算法