CF:1633D. Make Them Equal(广搜+背包)

14 篇文章 0 订阅
5 篇文章 1 订阅

题目链接

题意:有一个大小为n的整数数组a。最初,数组所有元素都为1.

可以执行如下操作:选定一个i和任意的x(x>0)然后把ai=ai+[ai/x](向下取整)

执行所有操作后,若ai==bi,那么你可以得到ci个金币。通过执行不超过k次的操作使得获得最大的金币数量。

1->bi的最小操作数,用广搜得到。所以用广搜预处理1->1000的所有最小操作数,然后来一遍01背包即可。

细节处理:由于k太大了,但是可以发现任意一个1->bi的操作数最多为20左右,所以最多操作数总和也不过2e4左右,所以在跑背包之前先判断一下k与总操作数的大小关系;

#include <bits/stdc++.h>
using namespace std;
const int N=1005;
int n,k;
int v[N];
int b[N];
int w[N];
int cost[N];
bool flag[N];
void solve(){
    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>b[i];
    for(int i=1;i<=n;i++) cin>>w[i];
    int sum=0;
    for(int i=1;i<=n;i++){
        v[i]=cost[b[i]];
        sum+=v[i];
    }
    int ans=0;
    if(sum<=k){
        for(int i=1;i<=n;i++) ans+=w[i];
        cout<<ans<<'\n';
    }else{
        static int f[1000005];
        memset(f,0,sizeof(f));
        for(int i=1;i<=n;i++){
            for(int j=k;j>=v[i];j--){
                f[j]=max(f[j],f[j-v[i]]+w[i]);
            }
        }
        cout<<f[k]<<'\n';
    }
}
void bfs(){
    queue<int> que;
    que.push(1);
    flag[1]=true;
    while(que.size()){
        int u=que.front();
        que.pop();
        for(int i=1;i<=u;i++){
            int t=u+u/i;
            if(t>=N) continue;
            if(flag[t]) continue;
            que.push(t);
            cost[t]=cost[u]+1;
            flag[t]=true;
        }
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    bfs();
    int t;cin>>t;
    while(t--) solve();
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值