• noip2017部分题目


    D1T3 逛公园

    题目描述

    策策同学特别喜欢逛公园。公园可以看成一张NN个点MM条边构成的有向图,且没有 自环和重边。其中1号点是公园的入口,NN号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间。

    策策每天都会去逛公园,他总是从1号点进去,从NN号点出来。

    策策喜欢新鲜的事物,它不希望有两天逛公园的路线完全一样,同时策策还是一个 特别热爱学习的好孩子,它不希望每天在逛公园这件事上花费太多的时间。如果1号点 到NN号点的最短路长为dd,那么策策只会喜欢长度不超过d + Kd+K的路线。

    策策同学想知道总共有多少条满足条件的路线,你能帮帮它吗?

    为避免输出过大,答案对PP取模。

    如果有无穷多条合法的路线,请输出-11。

    输入输出格式

    输入格式:

    第一行包含一个整数 TT, 代表数据组数。

    接下来TT组数据,对于每组数据: 第一行包含四个整数 N,M,K,PN,M,K,P,每两个整数之间用一个空格隔开。

    接下来MM行,每行三个整数a_i,b_i,c_iai,bi,ci,代表编号为a_i,b_iai,bi的点之间有一条权值为 c_ici的有向边,每两个整数之间用一个空格隔开。

    输出格式:

    输出文件包含 TT 行,每行一个整数代表答案。

    输入输出样例

    输入样例#1: 
    2
    5 7 2 10
    1 2 1
    2 4 0
    4 5 2
    2 3 2
    3 4 1
    3 5 2
    1 5 3
    2 2 0 10
    1 2 0
    2 1 0
    输出样例#1: 
    3
    -1
    
    

    说明

    【样例解释1】

    对于第一组数据,最短路为 33。 $1 – 5, 1 – 2 – 4 – 5, 1 – 2 – 3 – 5$ 为 33 条合法路径。

    【测试数据与约定】

    对于不同的测试点,我们约定各种参数的规模不会超过如下

    测试点编号  TT   NN   MM   KK   是否有0边
    1 5 5 10 0
    2 5 1000 2000 0
    3 5 1000 2000 50
    4 5 1000 2000 50
    5 5 1000 2000 50
    6 5 1000 2000 50
    7 5 100000 200000 0
    8 3 100000 200000 50
    9 3 100000 200000 50
    10 3 100000 200000 50

    对于 100%的数据, 1 le P le 10^9,1 le a_i,b_i le N ,0 le c_i le 10001P109,1ai,biN,0ci1000。

    数据保证:至少存在一条合法的路线。

    题意:求dis(1,n)<=dis(1,n)+k 的路径数

    设f[u][k]表示比 dis(1,u) 长度多 k 的路径数,则

            dp[v][k] = ∑dp[u][k+ dis[u]+w-dis[v]]  ((u,v)∈E)   //dis[i]表示从起点到点i的最短距离,w是(u,v)边权

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <queue>
     4 #include <algorithm>
     5 #include <cstring>
     6 #define R register
     7 #define NN 100001
     8 #define MM 200001
     9 using namespace std;
    10 int T,N,M,K,P;
    11 int head[NN],d[NN],f[NN][55],b[NN][55],ans;
    12 bool vis[NN],flag;
    13 struct edge{
    14     int u,v,w,next;
    15 }e[MM];
    16 inline int ri(){
    17     char c=getchar();int x=0,w=1;
    18     while(!isdigit(c)){if(c=='-')w=-1;c=getchar();}
    19     while( isdigit(c)){x=(x<<3)+(x<<1)+c-48;c=getchar();}
    20     return x*w;
    21 }
    22 inline void spfa(){
    23     queue<int> q;
    24     d[1]=0;
    25     q.push(1);
    26     int u;
    27     while(!q.empty()){
    28         u=q.front();q.pop();
    29         vis[u]=0;
    30         for(R int i=head[u];i;i=e[i].next){
    31             if(d[e[i].v]>d[u]+e[i].w){
    32                 d[e[i].v]=d[u]+e[i].w;
    33                 if(!vis[e[i].v])vis[e[i].v]=1,q.push(e[i].v);
    34             }
    35         }
    36     }
    37 }
    38 inline int dfs(int u,int step){
    39     if(b[u][step]==1||flag)return flag=1;
    40     if(b[u][step]==2)return f[u][step];
    41     b[u][step]=1;
    42     for(R int i=head[u],w;i;i=e[i].next){
    43         w=step+d[u]-d[e[i].v]-e[i].w;
    44         if(w>K||w<0)continue;
    45         f[u][step]+=dfs(e[i].v,w);
    46         f[u][step]%=P;
    47     }
    48     b[u][step]=2;
    49     return f[u][step];
    50 }
    51 int main(){
    52     T=ri();
    53     while(T--){
    54         N=ri(),M=ri(),K=ri(),P=ri();
    55         memset(head,0,sizeof(head));
    56         
    57         for(R int i=1;i<=M;++i){
    58             e[i].u=ri(),e[i].v=ri(),e[i].w=ri();
    59             e[i].next=head[e[i].u];
    60             head[e[i].u]=i;
    61         }//以上输入 
    62         
    63         memset(vis,0,sizeof(vis));
    64         memset(d,127,sizeof(d));
    65         spfa();//跑一边spfa找最短路 
    66         
    67         memset(head,0,sizeof(head));
    68         for(R int i=1;i<=M;++i){
    69             swap(e[i].u,e[i].v);
    70             e[i].next=head[e[i].u];
    71             head[e[i].u]=i;//反向连图 
    72         }
    73         
    74         memset(f, 0, sizeof(f));
    75         memset(b, 0, sizeof(b));
    76         f[1][0]=1,ans=0,flag=0;
    77         
    78         for(R int i=0;i<=K;++i){//枚举与mindis的差 
    79             ans+=dfs(N,i); //倒着搜 
    80             ans%=P; 
    81         }
    82         printf("%d
    ", flag ? -1 : ans);
    83     }
    84     return 0;
    85 }

    D2T1 奶酪

    题目描述

    现有一块大奶酪,它的高度为 hhh,它的长度和宽度我们可以认为是无限大的,奶酪 中间有许多 半径相同 的球形空洞。我们可以在这块奶酪中建立空间坐标系,在坐标系中, 奶酪的下表面为z=0z = 0z=0,奶酪的上表面为z=hz = hz=h。

    现在,奶酪的下表面有一只小老鼠 Jerry,它知道奶酪中所有空洞的球心所在的坐 标。如果两个空洞相切或是相交,则 Jerry 可以从其中一个空洞跑到另一个空洞,特别 地,如果一个空洞与下表面相切或是相交,Jerry 则可以从奶酪下表面跑进空洞;如果 一个空洞与上表面相切或是相交,Jerry 则可以从空洞跑到奶酪上表面。

    位于奶酪下表面的 Jerry 想知道,在 不破坏奶酪 的情况下,能否利用已有的空洞跑 到奶酪的上表面去?

    空间内两点P1(x1,y1,z1)P_1(x_1,y_1,z_1)P1(x1,y1,z1)、P2(x2,y2,z2)P2(x_2,y_2,z_2)P2(x2,y2,z2)的距离公式如下:

    dist(P1,P2)=(x1−x2)2+(y1−y2)2+(z1−z2)2mathrm{dist}(P_1,P_2)=sqrt{(x_1-x_2)^2+(y_1-y_2)^2+(z_1-z_2)^2}dist(P1,P2)=(x1x2)2+(y1y2)2+(z1z2)2

    输入输出格式

    输入格式:

    每个输入文件包含多组数据。

    的第一行,包含一个正整数 TTT,代表该输入文件中所含的数据组数。

    接下来是 TTT 组数据,每组数据的格式如下: 第一行包含三个正整数 n,hn,hn,h 和 rrr,两个数之间以一个空格分开,分别代表奶酪中空 洞的数量,奶酪的高度和空洞的半径。

    接下来的 nnn 行,每行包含三个整数 x,y,zx,y,zx,y,z,两个数之间以一个空格分开,表示空 洞球心坐标为(x,y,z)(x,y,z)(x,y,z)。

    输出格式:

    TTT 行,分别对应 TTT 组数据的答案,如果在第 iii 组数据中,Jerry 能从下 表面跑到上表面,则输出Yes,如果不能,则输出No (均不包含引号)。

    输入输出样例

    输入样例#1: 
    3 
    2 4 1 
    0 0 1 
    0 0 3 
    2 5 1 
    0 0 1 
    0 0 4 
    2 5 2 
    0 0 2 
    2 0 4 
    输出样例#1:
    Yes
    No
    Yes

    说明

    【输入输出样例 1 说明】

    第一组数据,由奶酪的剖面图可见:

    第一个空洞在(0,0,0)(0,0,0)(0,0,0)与下表面相切

    第二个空洞在(0,0,4)(0,0,4)(0,0,4)与上表面相切 两个空洞在(0,0,2)(0,0,2)(0,0,2)相切

    输出 Yes

    第二组数据,由奶酪的剖面图可见:

    两个空洞既不相交也不相切

    输出 No

    第三组数据,由奶酪的剖面图可见:

    两个空洞相交 且与上下表面相切或相交

    输出 Yes

    【数据规模与约定】

    对于 20%20\%20%的数据,n=1n = 1n=1,1≤h1 le h1h , r≤10,000r le 10,000r10,000,坐标的绝对值不超过 10,00010,00010,000。

    对于 40%40\%40%的数据,1≤n≤81 le n le 81n8, 1≤h1 le h1h , r≤10,000r le 10,000r10,000,坐标的绝对值不超过 10,00010,00010,000。

    对于80%80\%80%的数据, 1≤n≤1,0001 le n le 1,0001n1,000, 1≤h,r≤10,0001 le h , r le 10,0001h,r10,000,坐标的绝对值不超过10,00010,00010,000。

    对于 100%100\%100%的数据,1≤n≤1,0001 le n le 1,0001n1,000,1≤h,r≤1,000,000,0001 le h , r le 1,000,000,0001h,r1,000,000,000,T≤20T le 20T20,坐标的 绝对值不超过 1,000,000,0001,000,000,0001,000,000,000。

    emm 以下的代码不是原创 忘记了是哪里copy来的

    考虑并查集。如果一个能到达奶酪顶的空洞和一个能到达奶酪底的空洞有交,便可以。即有共同的祖先。

    当然我并不知道会不会有一个洞连接了奶酪顶和底...这不重要 这样的洞父亲就是本身

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 #define R register
     4 using namespace std;
     5 int f[1001];
     6 int find(int x){
     7     return f[x]==x ? x : f[x]=find(f[x]);
     8 }
     9 double dis(long long x,long long y,long long z,long long x1,long long y1,long long z1){
    10     return sqrt((x-x1)*(x-x1)+(y-y1)*(y-y1)+(z-z1)*(z-z1));
    11 }
    12 long long x[100001],y[100001],z[100001];
    13 int f1[100001],f2[100001];
    14 int main(){
    15     int t,n,h;long long r;
    16     scanf("%d",&t);
    17     for (int i=1;i<=t;i++){
    18         scanf("%d%d%ld",&n,&h,&r);
    19         int tot1=0;int tot2=0;
    20         for (R int j=1;j<=n;j++)f[j]=j; 
    21         for (R int j=1;j<=n;j++){
    22             scanf("%ld%ld%ld",&x[j],&y[j],&z[j]);
    23             if (z[j]+r>=h)f1[++tot1]=j;
    24             if (z[j]-r<=0)f2[++tot2]=j;
    25             for (R int k=1;k<=j;k++){
    26                 if (dis(x[j],y[j],z[j],x[k],y[k],z[k])<=2*r){
    27                     int a1=find(j),a2=find(k);
    28                     if (a1!=a2)f[a1]=a2;
    29                 }
    30             }
    31         }
    32         int s=0;
    33         for (int j=1;j<=tot1;j++){
    34             for (int k=1;k<=tot2;k++)
    35                 if (find(f1[j])==find(f2[k])){s=1; break;}
    36             if (s==1) break;
    37         }
    38         if (s==1) cout<<"Yes"<<endl;
    39         else cout<<"No"<<endl;
    40     }
    41     return 0;
    42 } 
  • 相关阅读:
    Python学习——列表
    第04组 Alpha冲刺(3/6)
    第04组 Alpha冲刺(2/6)
    第04组 Alpha冲刺(1/6)
    第04组 团队Git现场编程实战
    第04组 团队项目-需求分析报告
    团队项目-选题报告
    第二次结对编程作业
    第4组 团队展示
    第一次结对编程作业
  • 原文地址:https://www.cnblogs.com/flicker-five/p/10418430.html
Copyright © 2020-2023  润新知