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


    题目链接:

    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;
    }
  • 相关阅读:
    MySQL主库异常,从库手动切换为主库方案
    快速搭建应用服务日志收集系统(Filebeat + ElasticSearch + kibana)
    CentOS7设置DNS服务器
    nginx/iptables动态IP黑白名单实现方案
    Python批量复制和重命名文件
    centos 7 配置php运行环境 (新)
    配置Nginx和php-fpm用Sock套接字连接时,找不到php-fpm.sock的原因
    php-fpm nginx 9000端口
    nginx与php-fpm通信的两种方式
    centos 7.2 常用命令useradd的使用
  • 原文地址:https://www.cnblogs.com/yxg123123/p/7169601.html
Copyright © 2020-2023  润新知