0
点赞
收藏
分享

微信扫一扫

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

无聊到学习 2022-05-02 阅读 64

题目链接

题意:有一个大小为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;
}
举报

相关推荐

CF1065C Make It Equal

0 条评论