【算法】【背包动态规划】

1 阅读1分钟

Equalization


题目大意

题目大意

给定两个非负整数 xy,你可以执行任意次操作(包括零次):

  • 选择一个正整数 k
  • xy 除以 2^k(向下取整)
  • 操作成本为 2^k
  • 限制条件:同一个 k 值只能使用一次

目标:通过若干次操作,使得 x = y,求最小总成本。

代码

#include <bits/stdc++.h>  
using namespace std;  
using ll=long long;  
const int B=60;  
const ll inf=1e18;  
  
void so(){  
      
}int main(){  
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);  
    array<array<ll,B>,B>dp;  
    for(int i=0;i<B;i++){  
        for(int j=0;j<B;j++){  
            dp[i][j]=inf;  
        }  
    }dp[0][0]=0;//都不除代价为0  
    for(int k=0;k<B;k++){  
        for(int i=B-1;i>=0;i--){  
            for(int j=B-1;j>=0;j--){  
                if(dp[i][j]==inf)continue;  
                if(i+k<B){  
                    dp[i+k][j]=min(dp[i+k][j],dp[i][j]+(1ll<<k));  
                }if(j+k<B){  
                    dp[i][j+k]=min(dp[i][j+k],dp[i][j]+(1ll<<k));  
                }  
            }//背包(倒着)保证只用一次  
            //保证每个状态只用了一次
        }  
    }int t;cin>>t;  
    while(t--){  
        ll x,y;cin>>x>>y;  
        ll ans=inf;  
        for(ll i=0;i<B;i++){  
            for(ll j=0;j<B;j++){  
                if((x>>i)==(y>>j))ans=min(ans,dp[i][j]);  
            }  
        }  
        cout<<ans<<'\n';      
        }  
      
}

思路

只用一次并且有代价要想到背包dp