hdu6076

Security Check

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 239    Accepted Submission(s): 96


Problem Description
In airport of Bytetown, there are two long queues waiting for security check. Checking a person needs one minute, and two queues can be checked at the same time.



Picture from Wikimedia Commons


Two teams A and B are going to travel by plane. Each team has n players, ranked from 1 to n according to their average performance. No two players in the same team share the same rank. Team A is waiting in queue 1 while team B is waiting in queue 2 . Nobody else is waiting for security check.

Little Q is the policeman who manages two queues. Every time he can check one person from one queue, or check one each person from both queues at the same time. He can't change the order of the queue, because that will make someone unhappy. Besides, if two players Ai and Bj are being checked at the same time, satisfying |AiBj|k , they will make a lot of noise because their rank are almost the same. Little Q should never let that happen.

Please write a program to help Little Q find the best way costing the minimum time.
 

Input
The first line of the input contains an integer T(1T15) , denoting the number of test cases.

In each test case, there are 2 integers n,k(1n60000,1k10) in the first line, denoting the number of players in a team and the parameter k .

In the next line, there are n distinct integers A1,A2,...,An(1Ain) , denoting the queue 1 from front to rear.

Then in the next line, there are n distinct integers B1,B2,...,Bn(1Bin) , denoting the queue 2 from front to rear.
 

Output
For each test case, print a single line containing an integer, denoting the minimum time to check all people.
 

Sample Input
  
  
1 4 2 2 3 1 4 1 2 4 3
 

Sample Output
  
  
7
Hint
Time 1 : Check A_1. Time 2 : Check A_2. Time 3 : Check A_3. Time 4 : Check A_4 and B_1. Time 5 : Check B_2. Time 6 : Check B_3. Time 7 : Check B_4.

题意:现要检查两条队伍,有两种方式,一种是从两条队伍中任选一条检查一个人,第二种是在每条队伍中同时各检查一个,前提是两条队伍中的两个人的序号大于k。然后询问检查最少需要的时间。

题解:(不会做,看题解后做的,实力还是不行,多学多记,多学多记!)这道题首先给人感觉就是dp,其实也是这样的,但是会发现dp的话矩阵大小是6e4*6e4,时间空间上都不允许。于是机智的人就会发现,那个k非常的小,小到让人不敢相信,于是就对k做了无限yy。想到可以将dp分出来,那些差值小于k的直接暴力dp,复杂度也就o(nk),然后对于那些差值大于k的——在位置x和y为固定某个差值的情况小进行二分,找到理现在位置最近的一组x1、y1,使得其值之差小于k,则这个位置与初始位置的x、y之间的所有都是保证了两边的差值是大于k的,于是加为答案。(有点绕,具体看代码)

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <string>
#include <queue>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <bitset>
#include <functional>
#include <cctype>
#include <utility>
#include <stack>
using namespace std;
typedef long long ll;
const int INF = 1e9+7;
const int maxn = 6e4+7;
int n,k;
int que1[maxn],que2[maxn],pos2[maxn];//两个队伍,以及第二个队伍每个人对应位置
bool cmp(int a,int b){return a>b;}
vector<int> g[2*maxn];
int dp[maxn][27];

int dfs(int x,int y){
    if(!x||!y) return x+y;//如果某点为0,那么剩余的那个队伍就一个一个的减去
    if(abs(que1[x]-que2[y])<=k){
        int &v = dp[que1[x]][que1[x]-que2[y]+k];
        if(v) return v;
        return v = min(dfs(x-1,y),dfs(x,y-1))+1;
    }//两个值之差小于k,暴力dp
    vector<int>::iterator it = lower_bound(g[x-y+n].begin(),g[x-y+n].end(),x,cmp);//二分预先处理出来的数组。
    if(it==g[x-y+n].end()) return max(x,y);//如果以该距离差剩下的不存在小于k的
    int v = *it;
    return dfs(v,y-x+v)+x-v;//把中间那些等距且差值大于k的加入
}

void solve(){
    for(int i = n;i >= 1;i--){
        for(int j = que1[i]-k;j <= que1[i]+k;j++){
            g[i-pos2[j]+n].push_back(i);
        }
    }//处理出位置差为某个固定值且对应的值之差小于k的数组(vector)
    memset(dp,0,sizeof(dp));
    cout<<dfs(n,n)<<endl;
    return ;
}

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&k);
        for(int i = 0;i <= 2*n;i++) g[i].clear();
        for(int i = 1;i <= n;i++){
            scanf("%d",que1+i);
        }
        for(int i = 1;i <= n;i++){
            scanf("%d",que2+i);
            pos2[que2[i]] = i;
        }//输入
        solve();
    }
    return 0;
}

【资源说明】 1.项目代码功能经验证ok,确保稳定可靠运行。欢迎下载使用!在使用过程中,如有问题或建议,请及时私信沟通。 2.主要针对各个计算机相关专业,包括计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网等领域的在校学生、专业教师或企业员工使用。 3.项目具有丰富的拓展空间,不仅可作为入门进阶,也可直接作为毕设、课程设计、大作业、初期项目立项演示等用途。 4.当然也鼓励大家基于此进行二次开发。 5.期待你能在项目中找到乐趣和灵感,也欢迎你的分享和反馈! 本文介绍了基于QEM(Quadric Error Metrics,二次误差度量)的优化网格简化算法的C和C++实现源码及其相关文档。这一算法主要应用于计算机图形学领域,用于优化三维模型的多边形数量,使之在保持原有模型特征的前提下实现简化。简化的目的是为了提高渲染速度,减少计算资源消耗,以及便于网络传输等。 本项目的核心是网格简化算法的实现,而QEM作为该算法的核心,是一种衡量简化误差的数学方法。通过计算每个顶点的二次误差矩阵来评估简化操作的误差,并以此来指导网格简化过程。QEM算法因其高效性和准确性在计算机图形学中广泛应用,尤其在实时渲染和三维打印领域。 项目代码包含C和C++两种语言版本,这意味着它可以在多种开发环境中运行,增加了其适用范围。对于计算机相关专业的学生、教师和行业从业者来说,这个项目提供了丰富的学习和实践机会。无论是作为学习编程的入门材料,还是作为深入研究计算机图形学的项目,该项目都具有实用价值。 此外,项目包含的论文文档为理解网格简化算法提供了理论基础。论文详细介绍了QEM算法的原理、实施步骤以及与其他算法的对比分析。这不仅有助于加深对算法的理解,也为那些希望将算法应用于自己研究领域的人员提供了参考资料。 资源说明文档强调了项目的稳定性和可靠性,并鼓励用户在使用过程中提出问题或建议,以便不断地优化和完善项目。文档还提醒用户注意查看,以获取使用该项目的所有必要信息。 项目的文件名称列表中包含了加水印的论文文档、资源说明文件和实际的项目代码目录,后者位于名为Mesh-Simplification-master的目录下。用户可以将这些资源用于多种教学和研究目的,包括课程设计、毕业设计、项目立项演示等。 这个项目是一个宝贵的资源,它不仅提供了一个成熟的技术实现,而且为进一步的研究和学习提供了坚实的基础。它鼓励用户探索和扩展,以期在计算机图形学领域中取得更深入的研究成果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值