1. 程式人生 > >Codeforces 830A. Office Keys (背包dp+貪心) / (二分+貪心)

Codeforces 830A. Office Keys (背包dp+貪心) / (二分+貪心)

d+ 背包dp 表示 cnblogs name return set office sed

題目鏈接:

http://codeforces.com/problemset/problem/830/A

題意:

n個人,k個鑰匙(n<=k),p表示這些人要到達的位置

給出n個人的位置以及鑰匙的位置,問花時間最多的那個人用時最少是多少??

思路:

二分+貪心: 二分最少時間,需要對a,b位置數組排序,我們check函數只需要從左到右一個一個找過去,因為如果選後邊的點,可能會使結果更差,假如當前這個人選後面的點,那可能會選中後面的人可以選的唯一的鑰匙,不會使解更優。

技術分享

check(40)的時候答案是false,是錯誤的,因為第一個人把第二個人可以唯一選的鑰匙選上了。

復雜度是 O((n+k)*log(2e9))

dp+貪心:

dp[i][j]表示前i個人用前j把鑰匙 轉移: dp[i][j] = min(dp[i][j-1],max(dp[i-1][j-1],abs(a[i]-b[j])+abs(b[j]-p))); dp[i][j-1]: 表示不選第 j 把鑰匙 max(dp[i-1][j-1],abs(a[i]-b[j])+abs(b[j]-p)): 表示選第 j 把鑰匙,就是考慮前 i-1 個人用前 j-1 把鑰匙,第i個人用第j把鑰匙,取最長的時間,因為答案要最長的人的時間 顯然 取二者最小就是答案了 ----》 背包?

dp真奇妙啊!

代碼一:

#include <bits/stdc++.h>
using
namespace std; typedef long long ll; #define MS(a) memset(a,0,sizeof(a)) #define MP make_pair #define PB push_back const int INF = 0x3f3f3f3f; const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; inline ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();} while
(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();} return x*f; } ////////////////////////////////////////////////////////////////////////// const int maxn = 2e3+10; ll dp[maxn][maxn],a[maxn],b[maxn]; int main(){ int n,k,p; cin >> n >> k >> p; for(int i=1; i<=n; i++) cin >> a[i]; for(int i=1; i<=k; i++) cin >> b[i]; sort(a+1,a+1+n); sort(b+1,b+1+k); for(int i=0; i<=n; i++) for(int j=0; j<=k; j++) dp[i][j] = INFLL; for(int i=0; i<=k; i++) dp[0][i]=0; for(int i=1; i<=n; i++) for(int j=i; j<=k; j++){ dp[i][j] = min(dp[i][j-1],max(dp[i-1][j-1],abs(a[i]-b[j])+abs(b[j]-p))); } cout << dp[n][k] << endl; return 0; }

代碼二:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define MS(a) memset(a,0,sizeof(a))
#define MP make_pair
#define PB push_back
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
    return x*f;
}
//////////////////////////////////////////////////////////////////////////
const int maxn = 2e3+10;

int n,k,pos;
ll a[maxn],b[maxn];
bool used[maxn];

bool check(ll x){
    int p = 0;
    for(int i=1; i<=n; i++){
        while(p<=k){
            p++;
            if(1LL*(abs(a[i]-b[p])+abs(b[p]-pos))<=x) break;
        }
        if(p > k) return false;
    }
    return true;
}

int main(){
    cin >> n >> k >> pos;
    for(int i=1; i<=n; i++)
        a[i] = read();
    for(int i=1; i<=k; i++)
        b[i] = read();
    sort(a+1,a+n+1); sort(b+1,b+k+1);

    ll L=0,R=2e9,ans=INFLL;
    while(L<=R){
        ll mid = (L+R)/2;
        if(check(mid)) ans=mid,R=mid-1;
        else L = mid+1;
    }
    cout << ans << endl;


    return 0;
}

Codeforces 830A. Office Keys (背包dp+貪心) / (二分+貪心)