第45届国际大学生程序设计竞赛(ICPC)亚洲区域赛(上海)DM

D Walker

#include<bits/stdc++.h>
using namespace std;

/*double get_dis(double pos,double v,double n)
{
    double a=(pos+n)/v;
    double b=(n-pos+n)/v;
    return min(a,b);
}*/

int main()
{
    int t;
    cin>>t;
    while(t--){
        double n,p1,p2,v1,v2;
        cin>>n>>p1>>v1>>p2>>v2;
        double sum=9999999999999999;
        if(p1>p2){
            swap(p1,p2);
            swap(v1,v2);
        }
        
        //sum=min(sum,get_dis(p1,v1,n));
        //sum=min(sum,get_dis(p2,v2,n));
        sum=(min(p1,n-p1)+n)/v1;
        sum=min(sum,(min(p2,n-p2)+n)/v2);//一个人走*/
        
        sum=min(sum,max((n-p1)/v1,p2/v2));//相向走
        
        double l=p1,r=p2;
        for(int i=0;i<100;i++)//每人走一段
        {
            double mid=(l+r)/2;
            double ans1=(min(mid-p1,p1)+mid)/v1;
            double ans2=(min(n-p2,p2-mid)+n-mid)/v2;
            //double ans1=get_dis(p1,v1,mid);
            //double ans2=get_dis(n-p2,v2,n-mid);
            sum=min(sum,max(ans1,ans2));
            
            if(ans1<ans2)l=mid;//浮点二分
            else r=mid;
        }
        printf("%.10lf\n",sum);          
    }
    return 0;
}
二分:整数二分+浮点数二分

模板一

	while (l < r)
    {
        int mid = l + r >> 1;	//(l+r)/2
        if (check(mid))  r = mid;    // check()判断mid是否满足性质
        else l = mid + 1;
    }

模板二

	while (l < r)
    {
        int mid = l + r + 1 >> 1;	//(l+r+1)/2
        if (check(mid))  l = mid;
        else r = mid - 1;
    }

第一个模板是尽量往左找目标,第二个模板是尽量往右找目标。
只要是往左找答案,就用第一个模板,mid不用加一,r=mid,l加一;
只要是往右找答案,就用第二个模板,mid要加一,l=mid,r要减一;

模板三(浮点二分)

	while(r-l>1e-5) //需要一个精度保证
	{
		double mid = (l+r)/2;
		if(check(mid)) l=mid; //或r=mid;
		else r=mid; //或l=mid;
	}

浮点二分就相对简单多了,因为浮点除法不会取整,所以mid,l,r,都不用加1或减1.

参考博客:https://blog.csdn.net/Mr_dimple/article/details/114656142?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164994337116782184680662%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=164994337116782184680662&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_positive~default-1-114656142.142v8pc_search_result_control_group,157v4control&utm_term=%E4%BA%8C%E5%88%86&spm=1018.2226.3001.4187

M Gitignore

题意
给你n个类似于 a/b/c/d 这样的文件夹或者文件,定义为gitignore,即可以被忽略的目录,m个这样的目录,表示不能被ignore的目录。如果一个文件夹里面不是所有的文件都能被忽略的话就不能忽略这个文件夹,否则可以直接忽略这个文件夹。
问最后gitignore最简用几行可以表达 eg:
3 0
data/train
data/test
model

data/train 和 data/test 都可以被忽略 所以就可以用忽略 data/ 来表示忽略了这个文件夹

3 1
data/train
data/test
model
data/sample
由于data/sample不能被忽略,所以在写gitignore的时候就需要把
data/train
data/test
model 都写上

思路
1.设置答案初始为ans=n,如果有可以直接忽略的就ans-1
2.先把m个不能被直接忽略的目录打上标记mp[now] = 1 ,在1~n找的时候直接continue即可。
3.对于一整个文件夹都可以被忽略的情况,如果第一次遇到,就把mp[now] 设为2 表示当前这个s就代表一整个文件夹(因为不能忽略一整个文件夹,所以必须保留一个)
4.遇到mp[now]=2 的 就说明已经被忽略了,并且有一个当作整个被忽略的文件夹,ans-1

#include<bits/stdc++.h>
 using namespace std;
 const int maxn=110;
 map<string,int>mp;
 string a[maxn],b[maxn];
 void solve()
 {
     mp.clear();
     int n,m;
     scanf("%d%d",&n,&m);
     for(int i=1;i<=n;i++)cin>>a[i];
     for(int i=1;i<=m;i++)cin>>b[i];
     int ans=n;
     for(int i=1;i<=m;i++)
     {
         int len=b[i].size();
         string now="";
         for(int j=0;j<len;j++)
         {
             now+=b[i][j];
             if(b[i][j]=='/')
             {
                 mp[now]=1;//不能直接被忽略
             }
         }

     }
     for(int i=1;i<=n;i++)
     {
         int len=a[i].size();
         string now="";
         for(int j=0;j<len;j++)
         {
             now+=a[i][j];
             if(a[i][j]=='/'){
                if(mp[now]==1)continue;
                else if(mp[now]==0)mp[now]=2;//一整个文件夹可以直接忽略
                else if(mp[now]==2){//说明已经被忽略了,并且有当作一个整体被忽略的文件夹
                    ans--;
                    break;
                }
             }
         }
     }
     printf("%d",ans);
 }
 int main()
 {
     int t;
     scanf("%d",&t);
     while(t--){
        solve();
        if(t)puts("");
     }
     return 0;
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值