Tyvj NOIP全真模拟系列赛(3)游记

题目貌似做得越来越正经了,话说这次有了PDF,还有大数据呢…

1.铺瓷砖

【问题描述】

有一面很长很长的墙。 你需要在这面墙上贴上两行瓷砖。 你的手头有两种不同尺寸的瓷砖, 你希望用这两种瓷砖各贴一行。瓷砖的长可以用分数表示,贴在第一行的每块瓷砖长度为 AB ,贴在第二行的每块瓷砖长度为 CD 。 本问题中你并不需要关心瓷砖的宽度。

1

如上图所示, 两排瓷砖从同一起始位置开始向右排列,两排瓷砖的第一块的左端的缝隙是对齐的。 你想要知道, 最短铺多少距离后, 两排瓷砖的缝隙会再一次对齐。

【输入】

输入的第 1 行包含一个正整数 T,表示测试数据的组数。

接下来 T 行, 每行 4 个正整数 A, B, C, D,表示该组测试数据中,两种瓷砖的长度分别为 AB CD

【输出】

输出包含 T 行, 第 i 行包含一个分数或整数, 表示第 i 组数据的答案。 如果答案为分数,则以“ X/Y”的格式输出,不含引号。分数必须化简为最简形式。如果答案为整数,则输出一个整数 X。

【输入输出样例1】

2

【输入输出样例 1 说明】

对于第一组数据,第一行瓷砖贴 2 块,第二行贴 3 块,总长度都为 1,即在距离起始位置长度为 1 的位置两行瓷砖的缝隙会再次对齐。

对于第二组数据, 第一行瓷砖贴 5 块,第二行贴 3 块,总长度都为 52

【数据规模与约定】

对于 50%的数据, 1≤A,B,C,D≤20

对于 70%的数据, T≤10

对于 100%的数据, T≤100,000, 1≤A,B,C,D≤10,000

Solution:

我直接打了一个分数gcd…

#include<stdio.h>
#include<iostream>
#define ll long long
using namespace std;
ll GCD(ll a,ll b){
    if(b==0)return a;
    else return GCD(b,a%b);
}
pair<ll,ll>gcd(ll A,ll B,ll C,ll D){
//  cout<<A<<' '<<B<<' '<<C<<' '<<D<<endl;
    if(C==0)return make_pair(A,B);
    ll E=1LL*A*D/(B*C);
    ll son=1LL*A*D-1LL*B*C*E;
    ll mom=1LL*B*D;
    ll d=GCD(son,mom);
    return gcd(C,D,son/d,mom/d);
}
int main(){
    freopen("tile.in","r",stdin);
    freopen("tile.out","w",stdout);
    int T;
    scanf("%d",&T);
    while(T--){
        int A,B,C,D;
        scanf("%d %d %d %d",&A,&B,&C,&D);
        pair<long,long>d=gcd(A,B,C,D);
        long long son=1LL*A*C*d.second;
        long long mom=1LL*B*D*d.first;
        long long dd=GCD(son,mom);
        son/=dd;mom/=dd;
        if(mom==1)cout<<son<<endl;
        else cout<<son<<'/'<<mom<<endl;
    }
    return 0;
}

2.小 Y 的问题

【问题描述】

有个孩子叫小 Y,一天,小 Y 拿到了一个包含 n 个点和 n-1 条边的无向连通图, 图中的点用 1~n 的整数编号。小 Y 突发奇想,想要数出图中有多少个“Y 字形”。

一个“Y 字形”由 5 个不同的顶点 A、 B、 C、 D、 E 以及它们之间的 4 条边组成,其中 AB、BC、 BD、 DE 之间有边相连, 如下图所示。

3

同时,无向图中的每条边都是有一定长度的。一个“Y 字形”的长度定义为构成它的四条边的长度和。小 Y也想知道,图中长度最大的“Y 字形”长度是多少。

【输入】

第一行包含一个整数 n,表示无向图的点数。

接下来 n 行, 每行有 3 个整数 x、 y、 z, 表示编号为 x 和 y 的点之间有一条长度为 z 的边。

【 输出】

输出包含 2 行。

第 1 行包含一个整数,表示图中的“Y 字形”的数量。

第 2 行包含一个整数,表示图中长度最大的“Y 字形”的长度。

【输入输出样例 1】

4

【输入输出样例 1 说明】

图中共有 5 个“Y 字形”, 如图中用红色标出的部分所示。

5

其中,长度最大的“Y 字形”是编号 3、 5、 7、 4、 6 的顶点构成的那一个,长度为 9。

【数据规模与约定】

对于 30%的数据, n≤10

对于 60%的数据, n≤2,000

对于 100%的数据, n≤200,000, 1≤x,y≤n, 1≤z≤10,000

Solution:

直接枚举Y中的B点与C点,完成第二小问,至于第一小问,就是一个简单的组合了吧,不再赘述。

什么sort啊,for呀,都乱搞。

#include<stdio.h>
#include<iostream>
#include<vector>
#include<algorithm>
#define ll long long
#define M 200005
using namespace std;
struct Node{
    int to,w;
    bool operator <(const Node &a)const{
        return w>a.w;
    }
};
vector<Node>G[M];
int main(){
    freopen("question.in","r",stdin);
    freopen("question.out","w",stdout);
    int n,maxans=0;
    scanf("%d",&n);
    ll ans=0;
    for(int i=1;i<n;i++){
        int a,b,c;
        scanf("%d %d %d",&a,&b,&c);
        G[a].push_back((Node){b,c});
        G[b].push_back((Node){a,c});
    }
    for(int i=1;i<=n;i++){
        int cnt=0;
        if(G[i].size()<3)continue;
        for(int j=0;j<G[i].size();j++)
            if(G[G[i][j].to].size()>1)cnt+=G[G[i][j].to].size()-1;
        ans+=1LL*cnt*(G[i].size()-1)*(G[i].size()-2)/2;
    }
    cout<<ans<<endl;
    for(int i=1;i<=n;i++)
        sort(G[i].begin(),G[i].end());
    for(int i=1;i<=n;i++){
        if(G[i].size()<3)continue;
        for(int j=0;j<G[i].size();j++){
            int to=G[i][j].to,res=0;
            if(G[to].size()==1)continue;
            if(to==G[i][0].to)res=G[i][1].w+G[i][2].w;
            else if(to==G[i][1].to)res=G[i][0].w+G[i][2].w;
            else res=G[i][0].w+G[i][1].w;
            int d;
            if(G[to][0].to==i)d=G[to][1].w;
            else d=G[to][0].w;
            if(res+d+G[i][j].w>maxans)maxans=res+d+G[i][j].w;
        }
    }
    printf("%d\n",maxans);
    return 0;
}

3.水管工的难题

【问题描述】

你是一名优秀的水管工。 一天你遇到了一个棘手的难题。 你需要在一个长方体状的房间内连接一条贯穿房间内部的水管。房间的长为 X,宽为 Y,高为 Z, 整个房间可以看成是 X×Y×Z个小立方体空间组成的。 如果位房间建立直角坐标系,则房间内每个小立方体空间都可以用一个三维坐标(x,y,z)表示, 房间一角的小立方体的坐标为(1,1,1), 它的对角的坐标为(X,Y,Z),其余小立方体的坐标的三个维度都分别落在 1…X, 1…Y 和 1…Z 内。 水管的入口和出口已经开凿好了,它们位于长方体的表面(可能位于房间的地板、墙壁或天花板上),且正好占据了某个小立方体的一个面。下图展示了房间的立方体空间的划分方式和一种开凿水管出入口的方式。

6

你的手头只有一种形状的水管部件, 它呈 L 型,且正好占据了 4 个小立方体空间, 如下图所示, 灰色部分是水管部件两端的开口位置。

7

你可以任意旋转、翻转水管部件,然后将它的开口接到入口、 出口或者其它水管部件的开口上。 水管的开口必须正好接在入口或出口上才算接上,伸出房间外一截是不行的。 下图展示了一种两个水管部件的连接方式。

8

在连接水管时, 水管部件间不能相交,也不能伸出房间之外。房间内有一些小立方体空间已经被物品占据了,水管也不能经过那些格子。 另外,水管部件数量有限,你的手头只有12个这样的零件。

现在,给出房间的长、高、 宽, 以及入口、出口的位置和房间内物品的坐标,请你计算至少需要多少个这样的水管部件才能完成任务,或者判断无法完成任务。

【输入】

输入的第 1 行包含 4 个正整数 X, Y, Z, m,其中 X,Y,Z 表示房间的长、高、宽, m 表示房间中物品的数量。

输入的第 2 行包含 3 个正整数 x1, y1, z1, 和一个字符 ch。 其中(x1,y1,z1)是水管入口所在的小立方体的坐标。 ch 的值为’x’、 ‘y’或’z’, 用于指示入口所在的面。 当 ch 为’x’时,表示入口所在的面与 YZ 坐标平面平行, 当 ch 为’y’时,表示入口所在的面与 XZ 坐标平面平行,当 ch 为’z’时,表示入口所在的面与 XY 坐标平面平行。 输入保证入口所在的面在长方体表面上。 数字和数字、数字和字符间用一个空格隔开。

输入的第 3 行包含 3 个正整数 x2, y2, z2,和一个字符 ch, 表示水管出口的位置, 意义与格式同上。

接下来 m 行,每行包含三个正整数 xi, yi, zi,表示在坐标(xi,yi,zi)的小立方体空间内有物品。

【 输出】

输出包含 1 个整数,表示最少使用的水管部件的数量。 如果不能完成接水管的任务,输出“impossible”, 不含引号。

【输入输出样例 1】

9

【输入输出样例 1 说明】

入口和出口的位置如图所示:

10

【数据规模与约定】

对于 30%的数据, 1≤X,Y,Z≤5

对于 50%的数据, 1≤X,Y,Z≤10

对于 70%的数据, 1≤X,Y,Z≤15

对于 100%的数据, 1≤X,Y,Z≤20

Solution:

神烦的一道题。

主要算法就是迭代加深搜索,加上一些小优化:

  • 加入估价函数。
  • 优先向终点扩展。
  • 等等…

比赛的时候基本都想到了,还算不错,但是没写完,竟然水了20分,神奇!

一位神犇AK,真心服…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值