【CodeForces】 830A Office Keys

传送门

codeforces

luogu

题目描述

There are n people and k keys on a straight line. Every person wants to get to the office which is located on the line as well. To do that, he needs to reach some point with a key, take the key and then go to the office. Once a key is taken by somebody, it couldn‘t be taken by anybody else.

You are to determine the minimum time needed for all n people to get to the office with keys. Assume that people move a unit distance per 1 second. If two people reach a key at the same time, only one of them can take the key. A person can pass through a point with a key without taking it.

思路

  首先读入后,按照位置分别排序,然后处理一个dis数组,表示第i个人拿了第j把钥匙后去办公室的路程。 然后就是一个01背包,最开始的时候人是瓷的,写了三重循环,一直TLE,附上磁珠代码233333

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<math.h>
using namespace std;
int n,k,p;
int man[1005];
int key[2005];
int dis[1005][2005];
int dp[1005][2005];
inline int cmp(int a,int b){
    return a<b;
}
int minn(int a,int b){
    if(a>=b)return b;
    return a;
}
int maxx(int a,int b){
    if(a>=b)return a;
    return b;
}
int main(){
    //freopen("1.in","r",stdin);
    cin>>n>>k>>p;
    for(register int i=1;i<=n;i++){
        cin>>man[i];
    }
    for(register int i=1;i<=k;i++){
        cin>>key[i];
    }
    sort(man+1,man+n+1,cmp);
    sort(key+1,key+k+1,cmp);
    for(register int i=1;i<=n;i++){
        for(register int j=1;j<=k;j++){
            dis[i][j]=fabs(man[i]-key[j])+fabs(key[j]-p);
            dp[i][j]=999999999;
        }
    }
    dp[0][0]=0;
    //cout<<"fuck"<<endl;
    for(register int i=1;i<=n;i++){  //1-ige re
        for(register int j=i;j<=k;j++){ //1-j zhongxuanze
            int xx=minn(j,n);
            for(register int kk=i;kk<=xx;kk++){
                if(kk<1)continue;
                dp[i][j]=minn(dp[i][j],maxx(dp[i-1][kk-1],dis[kk][j]));
//                cout<<i<<‘ ‘<<j<<‘ ‘<<kk<<endl;
//                cout<<dp[i][j]<<‘ ‘<<dp[i-1][kk]<<‘ ‘<<dis[kk][j]<<endl<<endl;
            }
        }
    }
    // while(1){
    //     int x,y;
    //     cin>>x>>y;
    //     cout<<dp[x][y]<<endl;
    // }
    int ans=999999999;
    for(register int i=n;i<=k;i++){
        ans=min(ans,dp[n][i]);
    }
    cout<<ans<<endl;
}

  当时用kk来表示i-1个人一共拿到第kk把钥匙是的最大步数的最小值,就是因为枚举这个kk然后挂了,后来发现不需要枚举kk,因为dp[i][j]只能从dp[i][j-1]和dp[i-1][j-1]两种情况转移过来,分别表示不选第j把钥匙和第i个人选了第j把钥匙的情况。

  可以得到状态转移方程:

              dp[i][j]=min(dp[i][j-1],max(dp[i-1][j-1],dis[i][j]));

  还有,初始化很重要qwq,所有的dp[0][i]都等于0,剩下的所有都是2147483647。

附上代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<math.h>
using namespace std;
int n,k,p;
int man[1005];
int key[2005];
int dis[1005][2005];
int dp[1005][2005];
inline int cmp(int a,int b){
    return a<b;
}
int minn(int a,int b){
    if(a>=b)return b;
    return a;
}
int maxx(int a,int b){
    if(a>=b)return a;
    return b;
}
int main(){
    //freopen("1.in","r",stdin);
    cin>>n>>k>>p;
    for(register int i=1;i<=n;i++){
        cin>>man[i];
    }
    for(register int i=1;i<=k;i++){
        cin>>key[i];
    }
    sort(man+1,man+n+1,cmp);
    sort(key+1,key+k+1,cmp);
    for(register int i=0;i<=n;i++){
        for(register int j=0;j<=k;j++){
            dis[i][j]=fabs(man[i]-key[j])+fabs(key[j]-p);
            dp[i][j]=2147483647;
        }
    }
    for(register int i=0;i<=k;i++){
        dp[0][i]=0;
    }
    //cout<<"fuck"<<endl;
    for(register int i=1;i<=n;i++){  //1-ige re
        for(register int j=1;j<=k;j++){ //1-j zhongxuanze
            dp[i][j]=minn(dp[i][j-1],maxx(dp[i-1][j-1],dis[i][j]));
        }
    }
    // while(1){
    //     int x,y;
    //     cin>>x>>y;
    //     cout<<dp[x][y]<<endl;
    // }
    int ans=2147483647;
    for(register int i=n;i<=k;i++){
        ans=min(ans,dp[n][i]);
    }
    cout<<ans<<endl;
}

原文地址:https://www.cnblogs.com/Fang-Hao/p/8460599.html

时间: 2024-08-29 08:26:35

【CodeForces】 830A Office Keys的相关文章

题解【POJ1160】Post Office

[POJ1160]Post Office Description There is a straight highway with villages alongside the highway. The highway is represented as an integer axis, and the position of each village is identified with a single integer coordinate. There are no two village

【原创】利用Office宏实现powershell payload远控

本文将演示使用Veil-Evasion生成远控所需要的payload以及监听器,然后使用MacroShop生成payload 相关的VBA代码,最后演示将VBA代码写入.doc文本文档的宏中. 环境:虚拟机_Kali          依赖:Veil-Evasion.MacroShop 0x00 安装Veil-Evasion.MacroShop (老鸟可绕过) 本例采用git 安装. 打开Veil-Evasion的github页面:https://github.com/Veil-Framewor

【codeforces】【比赛题解】#854 CF Round #433 (Div.2)

cf一如既往挺丧 看丧题点我! [A]分数 Petya是数学迷,特别是有关于分数的数学.最近他学了所谓一个分数被叫做"真分数"当且仅当其分子小于分母,而一个分数被叫做"最简分数"当且仅当其分子分母互质.在闲暇时间,Petya在用计算器研究:如何把最简真分数转换为小数等问题.有一天他不小心把除号(÷)按成了加号(+),导致他得到了分子与分母的和.Petya想要得到他原来的分数,但他很快发现这不是唯一的.所以现在他想要知道最大的最简真分数使得其分子与分母的和为n. 输入

【CodeForces】835D Palindromic characteristics

[算法]区间DP [题解]涉及回文问题的区间DP都可以用类似的写法,就是h[i][j]表示i~j是否回文,然后就可以O(1)判断回文了. f[i][j]=k表示该字符串是k-th字符串,因为首先要求回文,既然回文那么左半边和右半边就肯定一样了. #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=5010; int f[maxn][maxn]

【codeforces】【比赛题解】#849 CF Round #431 (Div.2)

cf的比赛越来越有难度了--至少我做起来是这样. 先看看题目吧:点我. 这次比赛是北京时间21:35开始的,算是比较良心. [A]奇数与结束 "奇数从哪里开始,又在哪里结束?梦想从何处起航,它们又是否会破灭呢?" 给定一个长度为n的序列.确定能不能将序列分成奇数个长度为奇数的非空字串,而且这其中每个子串以奇数开头,以奇数结尾.可以只分成一个(1也是奇数). 输入 第一行一个正整数n,表示序列长度. 第二行n个整数,表示序列中的元素. 输出 输出"Yes"或"

【CodeForces】841C. Leha and Function(Codeforces Round #429 (Div. 2))

[题意]定义函数F(n,k)为1~n的集合中选择k个数字,其中最小数字的期望. 给定两个数字集A,B,A中任意数字>=B中任意数字,要求重组A使得对于i=1~n,sigma(F(Ai,Bi))最大. [算法]数学结论+数学期望+排序 [题解]很无奈,这题放在div2 C,难以推导的期望公式,广为人知的结论,容易观察样例得出的做法,都体现了这道题的不合理性. F(n,k)=(n+1)/(k+1) 公式推导可能触及我的知识盲区了QAQ 得到公式后,显然要求k尽可能小,n尽可能大,经验告诉我们随着两数

【CodeForces】585 E. Present for Vitalik the Philatelist

[题目]E. Present for Vitalik the Philatelist [题意]给定n个数字,定义一种合法方案为选择一个数字Aa,选择另外一些数字Abi,满足?gcd(Aa,Abi)=1,且gcd(Ab1...Abx)≠1,求方案数取模1e9+7.2<=n<=5*10^5,2<=ai<=10^7. [算法]数论,计数问题 [题解]

【CodeForces】578 C. Weakness and Poorness

[题目]C. Weakness and Poorness [题意]给定含n个整数的序列ai,定义新序列为ai-x,要使新序列的最大子段和绝对值最小,求实数x.n<=2*10^5. [算法]二分||三分||计算几何(凸包) [题解]Editorial 令正数最大子段和为A,负数最大子段和为B,绝对值是max(A,B).当x从小到大变化时,A由大变小,B由小变大. 容易发现这是一个下凸函数,可以用三分法求解. 但是,这道题卡精度(-11会WA,-12会T),解决方法是根据复杂度把循环次数卡到极限而不

【CodeForces】F. Letters Removing

[题目]F. Letters Removing [题意]给定只含小写字母.大写字母和数字的字符串,每次给定一个范围要求删除[l,r]内的字符c(l和r具体位置随删除变动),求m次操作后的字符串.n<=2*10^5. [算法]树状数组+平衡树(set) [题解]因为坐标是序列变动后的,动态坐标可以转化为找到第l个存在的数字到第r个存在的数字之间的范围. 将序列中存在记为1,删除记为0,转化为找前缀和恰好为l和r的位置,这是树状数组的经典操作,详见这篇题解介绍的方法(简单的排名功能) 找到l和r在原