German Collegiate Programming Contest 2018 训练题解

鏖战4小时多 过了9个题
在这里插入图片描述

A题输入过于阴间,不会转化成建树。
K读不太懂 - -

C - Coolest Ski Route (C题)
给了我们n个点以及m条有边权的边,因为是滑雪,所以是单向边,问从一个点出发能最远滑多远.
分析: 直接存一下图 然后dfs 每个点 加了一点记忆化就过了


vector <pair<ll,ll> >vec[1100];
ll cnt[1100];
ll dfs(ll rt){
    
    
if(cnt[rt]!=-1){
    
    
    return cnt[rt];
}
ll sum=0;
for(int i=0;i<vec[rt].size();i++){
    
    
  sum=max(sum,vec[rt][i].second+dfs(vec[rt][i].first));

}
return cnt[rt]=sum;
}
signed main(){
    
    
ll n,m;
read(n);
read(m);
memset(cnt,-1,sizeof(cnt));
while(m--){
    
    
    ll u,v,w;
    read(u);
    read(v);
    read(w);
    vec[u].push_back(mp(v,w));
}
ll add=0;
for(int i=1;i<=n;i++){
    
    
    add=max(add,dfs(i));
}
printf("%lld\n",add);
}

Down the Pyramid D题
按题目意思说的就是一种搭建金字塔,使得一个块下面两个块的和与它相等,现在他给了我们n个数,我们要构造他下面的n+1块砖是什么值符合构造的种数有多少种。
分析: 其实想一想 就是一个范围的维护 维护结束的【L R】区间就是答案

int a[maxn];
signed main() {
    
    
	IOS;
	int n;cin>>n;
	FOR2(i,1,n) cin>>a[i];
	int maxx=a[1],minn=0;
	int cnt=a[1];
	FOR2(i,2,n) {
    
    
		cnt=a[i]-cnt;
		if(i&1) maxx=min(maxx,cnt);
		else minn=max(minn,0-cnt);
	} 
	if(maxx<minn) cout<<0;
	else cout<<maxx-minn+1;
    return 0;
}

E - Expired License E 题

题目大概意思就是 给你两个实数,问存不存在两个素数的比值跟他俩的比值是一模一样的,不存在输出imporisble 题目的实数保证小数点后最多5位,我直接字符串输入把实数变成整数。
如果a : b = prime _1: prime_2
因为质数已经是最简型了,所以直接把a .b 除去gcd 再判断剩下的是不是都是质数就OK 注意特判 2 2 的情况

F - Fighting Monsters F 题
挺简单的,推一下式子你会发现就是问你n个数里面有没有相邻的两项斐波那契数列
H - Hyper Illuminati 这个直接暴力枚举就OK
I - It’s Time for a Montage 暴力枚举

L - Logic Puzzle L题
意思是一张nm的地雷图,现在给你(n+2)(m+2)的地雷数量分布情况,意思是以地雷图中的点的坐标为中心的3*3矩阵,现在问我们能不能还原回去那个地雷图或者说明这个是不可能的 。

分析: 没有地雷的点 它的一圈必定有0而且没有负数 不管什么时候只要有负数一定无法构造。那么我的思路就是枚举地雷图 依次check
如果此处没地雷就填一个。 有地雷就把它的一圈全部 -1 最终检查一次整个地雷分布情况是不是全是0 ,然后输出已经存下的地雷图


ll mapp[500][500];
char s[500][500];
ll check(ll x,ll y){
    
    
// 以x  y为中心的 3*3  矩阵
ll f=0;
ll NO=0;
ll Y=0;
//  判断是不是 。
for(int i=x-1;i<=x+1;i++){
    
    

    for(int j=y-1;j<=y+1;j++){
    
    
    if(mapp[i][j]==0){
    
    
     f++;
    }
    if(mapp[i][j]<0){
    
    
    NO++;
    }
    if(mapp[i][j]>0){
    
    
        Y++;
    }
    }
}

if(NO){
    
    
    printf("impossible\n");
 //  printf("%lld  %lld\n",x,y);
  exit(0);
}
if(f){
    
    
//  该点为0
return 0;
}
if(Y==9){
    
    

  for(int i=x-1;i<=x+1;i++){
    
    

    for(int j=y-1;j<=y+1;j++){
    
    
   mapp[i][j]--;
    }
}

   return 1;

}


}
ll n,m;
void init(){
    
    

for(int i=1;i<=n+2;i++){
    
    
    for(int j=1;j<=m+2;j++){
    
    

      printf("%lld ",mapp[i][j]);
    }
   printf("\n");
}

printf("--------------------\n");

}
signed main(){
    
    


read(n);
read(m);
for(int i=1;i<=n+2;i++){
    
    

    for(int j=1;j<=m+2;j++){
    
    

    read(mapp[i][j]);
    }
}

for(int i=2;i<=n+1;i++){
    
    

    for(int j=2;j<=m+1;j++){
    
    

     ll op=check(i,j);
   //  init();

     if(op==0){
    
    
     s[i][j]='.';
     continue;
     }
     if(op==1){
    
    
        s[i][j]='X';
     }

    }

}

for(int i=1;i<=n+2;i++){
    
    
    for(int j=1;j<=m+2;j++){
    
    
        if(mapp[i][j]!=0){
    
    
          printf("impossible");
          return 0;
        }
    }
}
for(int i=2;i<=n+1;i++){
    
    
    for(int j=2;j<=m+1;j++){
    
    
        printf("%c",s[i][j]);
    }
    printf("\n");
}


}

M - Mountaineers M题
辛格牛逼~~ 在这里插入图片描述
其实LCA也能跑 。

B题 B - Battle Royale 计算几何
给了我们两个点A B的坐标并给了两个圆的信息, 大圆把小圆包含着,现在求从A 到B 且不经过小圆,不走出大圆的最短路径。保证A B的直线距离是横穿小圆的。
分析: 草稿纸上简单证明了下,A,B点并不会直接向着圆心走到⚪上,这样子的距离比从切线走到圆上要长,这一点很显然。那么相当于求A走切线再走圆弧再走B的切线这两段路程。
在这里插入图片描述
那么直接算一下A到圆心,B到圆心,AB的距离,构造三角形算一下圆心角的弧度,另外的减去两段多余的弧度,最终勾股定理求一下点到切点的距离 ,搞了一个小时才AC

猜你喜欢

转载自blog.csdn.net/weixin_45948940/article/details/113728255