2019天梯赛第三次训练赛

Posted taozi1115402474

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019天梯赛第三次训练赛相关的知识,希望对你有一定的参考价值。

7-1 求整数均值 (10 分)

本题要求编写程序,计算4个整数的和与平均值。题目保证输入与输出均在整型范围内。

输入格式:

输入在一行中给出4个整数,其间以空格分隔。

输出格式:

在一行中按照格式“Sum = 和; Average = 平均值”顺序输出和与平均值,其中平均值精确到小数点后一位。

输入样例:

1 2 3 4

输出样例:

  Sum = 10; Average = 2.5

水题

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     int a,b,c,d;
 7     scanf("%d%d%d%d",&a,&b,&c,&d); 
 8     printf("Sum = %d; Average = %.1f
", a+b+c+d,(a+b+c+d)/4.);
 9     return 0;
10 }
7-2 输出带框文字 (5 分)

本题要求编写程序,输出指定的带框文字。

输入格式:

本题无输入

输出格式:

按照下列格式输出带框文字。

************
  Welcome
************

水题

1 #include<bits/stdc++.h>
2 using namespace std;
3 
4 int main()
5 {
6     printf("************
  Welcome
************");
7     return 0;
8 }
7-3 混合类型数据格式化输入 (5 分)

本题要求编写程序,顺序读入浮点数1、整数、字符、浮点数2,再按照字符、整数、浮点数1、浮点数2的顺序输出。

输入格式:

输入在一行中顺序给出浮点数1、整数、字符、浮点数2,其间以1个空格分隔。

输出格式:

在一行中按照字符、整数、浮点数1、浮点数2的顺序输出,其中浮点数保留小数点后2位。

输入样例:

2.12 88 c 4.7

输出样例:

c 88 2.12 4.70

水题

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     double a,b;
 7     char c;
 8     int d;
 9     scanf("%lf %d %c %lf",&a,&d,&c,&b);
10     printf("%c %d %.2f %.2f",c,d,a,b);
11     return 0;
12 }
7-4 用天平找小球 (10 分)

三个球A、B、C,大小形状相同且其中有一个球与其他球重量不同。要求找出这个不一样的球。

输入格式:

输入在一行中给出3个正整数,顺序对应球A、B、C的重量。

输出格式:

在一行中输出唯一的那个不一样的球。

输入样例:

1 1 2

输出样例:

C

水题

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3  
 4 int main()
 5 {
 6     int a,b,c;
 7     scanf("%d%d%d",&a,&b,&c);
 8     if(a==b)printf("C");
 9     else if(a==c)printf("B");
10     else printf("A");
11     return 0;
12 }
7-5 IP地址转换 (20 分)

一个IP地址是用四个字节(每个字节8个位)的二进制码组成。请将32位二进制码表示的IP地址转换为十进制格式表示的IP地址输出。

输入格式:

输入在一行中给出32位二进制字符串。

输出格式:

在一行中输出十进制格式的IP地址,其由4个十进制数组成(分别对应4个8位的二进制数),中间用“.”分隔开。

输入样例:

11001100100101000001010101110010

输出样例:

204.148.21.114

水题

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     char data[35];
 7     int IP[4];
 8     scanf("%s",data);
 9     for (int i=0;i<4;i++) 
10     {
11         int temp=0,x=1;
12         for(int j=7;j>=0;j--) 
13         {
14             temp+=x*(data[i*8+j]-0);
15             x*=2;
16         }
17         IP[i]=temp;
18     }
19     printf("%d.%d.%d.%d",IP[0],IP[1],IP[2],IP[3]);
20     return 0;
21 }
7-6 找出总分最高的学生 (15 分)

给定N个学生的基本信息,包括学号(由5个数字组成的字符串)、姓名(长度小于10的不包含空白字符的非空字符串)和3门课程的成绩([0,100]区间内的整数),要求输出总分最高学生的姓名、学号和总分。

输入格式:

输入在一行中给出正整数N(<=10)。随后N行,每行给出一位学生的信息,格式为“学号 姓名 成绩1 成绩2 成绩3”,中间以空格分隔。

输出格式:

在一行中输出总分最高学生的姓名、学号和总分,间隔一个空格。题目保证这样的学生是唯一的。

输入样例:

5
00001 huanglan 78 83 75
00002 wanghai 76 80 77
00003 shenqiang 87 83 76
10001 zhangfeng 92 88 78
21987 zhangmeng 80 82 75

输出样例:

zhangfeng 10001 258

直接处理比大小,或者结构体排序

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     int n,a,b,c,maxx=0;
 7     char name[15],num[10];
 8     char mname[15],mnum[10];
 9     scanf("%d",&n);
10     for(int i=0;i<n;i++)
11     {
12         scanf("%s%s%d%d%d",num,name,&a,&b,&c);
13         int sum=a+b+c;
14         if(sum>maxx)
15         {
16             maxx=sum;
17             strcpy(mname,name);
18             strcpy(mnum,num);
19         }
20     }
21     printf("%s %s %d",mname,mnum,maxx);
22     return 0;
23 }
7-7 链表去重 (25 分)

给定一个带整数键值的链表 L,你需要把其中绝对值重复的键值结点删掉。即对每个键值 K,只有第一个绝对值等于 K 的结点被保留。同时,所有被删除的结点须被保存在另一个链表上。例如给定 L 为 21→-15→-15→-7→15,你需要输出去重后的链表 21→-15→-7,还有被删除的链表 -15→15。

输入格式:

输入在第一行给出 L 的第一个结点的地址和一个正整数 N(<=105,为结点总数)。一个结点的地址是非负的 5 位整数,空地址 NULL 用 -1 来表示。

随后 N 行,每行按以下格式描述一个结点:

地址 键值 下一个结点

其中地址是该结点的地址,键值是绝对值不超过104的整数,下一个结点是下个结点的地址。

输出格式:

首先输出去重后的链表,然后输出被删除的链表。每个结点占一行,按输入的格式输出。

输入样例:

00100 5
99999 -7 87654
23854 -15 00000
87654 15 -1
00000 -15 99999
00100 21 23854

输出样例:

00100 21 23854
23854 -15 99999
99999 -7 -1
00000 -15 87654
87654 15 -1

数组模拟链表,去重用map

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int N=1e5+5;
 5 int nxt[N],val[N],aa[N],pos[N];
 6 map<int,int>ma;
 7 vector< pair<int,int> >v1,v2;
 8 int main()
 9 {
10     int st,n,a,b,x;
11     scanf("%d%d",&st,&n);
12     for(int i=0;i<n;i++)
13     {
14         scanf("%d%d%d",&a,&x,&b);
15         nxt[a]=b,val[a]=x;
16     }
17     int tmp=st,cnt=0;
18     while(1)
19     {
20         ++cnt;
21         pos[cnt]=tmp;
22         aa[cnt]=val[tmp];
23         if(nxt[tmp]==-1)break;
24         tmp=nxt[tmp];
25     }
26     for(int i=1;i<=cnt;i++)
27     {
28         int x=abs(aa[i]);
29         if(!ma[x])
30         {
31             ma[x]=1;
32             v1.push_back({pos[i],aa[i]});
33         }
34         else
35             v2.push_back({pos[i],aa[i]});
36     }
37     for(int i=0;i<v1.size();i++)
38     {
39         printf("%05d %d ",v1[i].first,v1[i].second);
40         if(i==(int)v1.size()-1)printf("-1
");
41         else printf("%05d
",v1[i+1].first);
42     }
43     for(int i=0;i<v2.size();i++)
44     {
45         printf("%05d %d ",v2[i].first,v2[i].second);
46         if(i==(int)v2.size()-1)printf("-1
");
47         else printf("%05d
",v2[i+1].first);
48     }
49     return 0;
50 }
7-8 一元多项式求导 (20 分)

设计函数求一元多项式的导数。

输入格式:

以指数递降方式输入多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。

输出格式:

以与输入相同的格式输出导数多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。

输入样例:

3 4 -5 2 6 1 -2 0

输出样例:

12 3 -10 1 6 0

求导,常数求导0,(ax^b)‘=(a*b)x^(b-1)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     int flag=0,c,e;
 7     while(1)
 8     {
 9         scanf("%d%d",&c,&e);
10         if(e)
11         {
12             if(flag)printf(" ");
13             printf("%d %d",c*e,e-1);
14             flag=1;
15         }
16         if(getchar()!= )break;
17     }
18     if(!flag)printf("0 0");
19     return 0;
20 }
7-9 水仙花数 (20 分)

水仙花数是指一个N位正整数N(>=3),它的每个位上的数字的N次幂之和等于它本身。例如:153=13+53+33本题要求编写程序,计算所有N位水仙花数。

输入格式:

输入在一行中给出一个正整数N(3<=N<=7)。

输出格式:

按递增顺序输出所有N位水仙花数,每个数字占一行。

输入样例:

3

输出样例:

153
370
371
407

[10^(n-1),10^n)枚举每个数是不是

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int Pow(int a,int n)
 4 {
 5     int sum=a;
 6     for(int i=1;i<n;i++)
 7         sum*=a;
 8     return sum;
 9 }
10 int main()
11 {
12     int n;
13     cin>>n;
14     int a=Pow(10,n-1),b=Pow(10,n);
15     for(int i=a;i<b;i++)
16     {
17         int sum=0,div=1;
18         for(int j=0;j<n;j++)
19             sum+=Pow(i/div%10,n),div*=10;
20         if(sum==i)
21             printf("%d
",i);
22     }
23     return 0;
24 }
7-10 求一元二次方程的根 (20 分)

本题目要求一元二次方程的根,结果保留2位小数。

输入格式:

输入在一行中给出3个浮点系数a、b、c,中间用空格分开。

输出格式:

根据系数情况,输出不同结果:

1)如果方程有两个不相等的实数根,则每行输出一个根,先大后小;

2)如果方程有两个不相等复数根,则每行按照格式“实部+虚部i”输出一个根,先输出虚部为正的,后输出虚部为负的;

3)如果方程只有一个根,则直接输出此根;

4)如果系数都为0,则输出"Zero Equation";

5)如果a和b为0,c不为0,则输出"Not An Equation"。

输入样例1:

2.1 8.9 3.5

输出样例1:

-0.44
-3.80

输入样例2:

1 2 3

输出样例2:

-1.00+1.41i
-1.00-1.41i

输入样例3:

0 2 4

输出样例3:

-2.00

输入样例4:

0 0 0

输出样例4:

Zero Equation

输入样例5:

0 0 1

输出样例5:

Not An Equation

哇,样例这么多,写完过样例一想肯定满分了,一看???后来发现有精度问题,考虑了一下0才AC

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     double a,b,c;
 7     while(cin>>a>>b>>c)
 8     {
 9         if(a==0&&b==0)
10         {
11             if(c==0)cout<<"Zero Equation
";
12             else cout<<"Not An Equation
";
13         }
14         else if(a==0)
15         {
16             double x=-c/b;
17             if(fabs(x)<=1e-6)x=0;
18             printf("%.2f
",x);
19         }
20         else
21         {
22             double d=b*b-4*a*c;
23             if(d==0)
24             {
25                 double x=-b/(2*a);
26                 if(fabs(x)<=1e-6)x=0;
27                 printf("%.2f
",x);
28             }
29             else if(d>0)
30             {
31                 double x1=(-b+sqrt(d))/(2*a);
32                 double x2=(-b-sqrt(d))/(2*a);
33                 if(x1<x2)swap(x1,x2);
34                 printf("%.2f
%.2f
",x1,x2);
35             }
36             else
37             {
38                 double s=-b/(2*a);
39                 double f=sqrt(-d)/(2*a);
40                 if(fabs(s)<=1e-6)s=0;
41                 printf("%.2f+%.2fi
%.2f-%.2fi
",s,fabs(f),s,fabs(f));
42             }
43         }
44     }
45     return 0;
46 }
7-11 畅通工程之局部最小花费问题 (35 分)

某地区经过对城镇交通状况的调查,得到现有城镇间快速道路的统计数据,并提出“畅通工程”的目标:使整个地区任何两个城镇间都可以实现快速交通(但不一定有直接的快速道路相连,只要互相间接通过快速路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建快速路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全地区畅通需要的最低成本。

输入格式:

输入的第一行给出村庄数目N(1<=N<=100);随后的N*(N-1)/2行对应村庄间道路的成本及修建状态:每行给出4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态 — 1表示已建,0表示未建。

输出格式:

输出全省畅通需要的最低成本。

输入样例:

4
1 2 1 1
1 3 4 0
1 4 1 1
2 3 3 0
2 4 2 1
3 4 5 0

输出样例:

3

最小生成树,已经建好了的花费为0

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 struct edge
 5 {
 6     int u,v,w; 
 7 }e[5005];
 8 bool cmp(edge a,edge b)
 9 {
10     return a.w<b.w;
11 }
12 int f[105];
13 int find(int x)
14 {
15     return f[x]==x?x:f[x]=find(f[x]);
16 }
17 int n,m;
18 int kru()
19 {
20     sort(e,e+m,cmp);
21     int ans=0,cnt=0;
22     for(int i=0;i<m;i++)
23     {
24         int fu=find(e[i].u);
25         int fv=find(e[i].v);
26         if(fu!=fv)
27         {
28             f[fu]=fv;
29             ans+=e[i].w;
30             if(++cnt==n-1)break;
31         }
32     }
33     return ans;
34 }
35 int main()
36 {
37     scanf("%d",&n);
38     m=n*(n-1)/2;
39     for(int i=1;i<=n;i++)f[i]=i;
40     for(int i=0,x;i<m;i++)
41     {
42         scanf("%d%d%d%d",&e[i].u,&e[i].v,&e[i].w,&x);
43         if(x)e[i].w=0;
44     }
45     printf("%d
",kru());
46     return 0;
47 }
7-12 迷你搜索引擎 (35 分)

实现一种简单的搜索引擎功能,快速满足多达105条关键字查询请求。

输入格式:

输入首先给出正整数 N(<=100),为文件总数。随后按以下格式给出每个文件的内容:第一行给出文件的标题,随后给出不超过 100 行的文件正文,最后在一行中只给出一个字符 #,表示文件结束。每行不超过 50 个字符。在 N 个文件内容结束之后,给出查询总数 M(<=105),随后 M 行,每行给出不超过 10 个英文单词,其间以空格分隔,每个单词不超过 10 个英文字母,不区分大小写。

输出格式:

针对每一条查询,首先在一行中输出包含全部该查询单词的文件总数;如果总数为 0,则输出 Not Found。如果有找到符合条件的文件,则按输入的先后顺序输出这些文件,格式为:第1行输出文件标题;随后顺序输出包含查询单词的那些行内容。注意不能把相同的一行重复输出。

输入样例:

4
A00
Gold
silver truck
#
A01
Shipment of gold
damaged
in a fire
#
A02
Delivery
of silver
arrived in
a silver
truck
#
A03
Shipment of gold
arrived in
a truck
#
2
what ever
silver truck

输出样例:

0
Not Found
2
A00
silver truck
A02
of silver
a silver
truck

查询10^5很大,考虑最暴力O(M*N^2)达到了10^9,莽一发,OK,25分超时1个样例

发现可以优化,单词用map存,映射到vector<pair<int,int>>表示第first个文件第second个位置

对于每个询问,map查找,由于它要每个文件所有单词都出现过,还得开数组统计单词出现次数

最后输出的时候,得按照文件顺序和位置排个序

这里还要注意不区分大小写,重复的问题

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 struct oo
 5 {
 6     string out;
 7     int I,POS;
 8     bool operator<(const oo &D){
 9         return I<D.I||(I==D.I&&POS<D.POS);
10     }
11 };
12 map<string,vector<pair<int,int>>>ma;
13 int main()
14 {
15     ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
16     int T,Q;
17     string ans[105][105],s,sb;
18     cin>>T;cin.get();
19     for(int i=1;i<=T;i++)
20     {
21         getline(cin,ans[i][0]);//文件名 
22         int pos=1;
23         while(getline(cin,ans[i][pos]))//silver {j,i}第j个文件第i行 
24         {
25             string fal=ans[i][pos];
26             if(ans[i][pos][0]==#)break;
27             for(int j=0;j<fal.size();j++)if(fal[j]>=A&&fal[j]<=Z)fal[j]+=32;
28             stringstream ss(fal);
29             while(ss>>s)ma[s].push_back({i,pos});
30             pos++;
31         }
32     }
33     cin>>Q;cin.get();
34     while(Q--)
35     {
36         getline(cin,sb);
37         for(int i=0;i<sb.size();i++)if(sb[i]>=A&&sb[i]<=Z)sb[i]+=32;
38         int cs[105]={0};//cs[i]表示i个文件出现了几次单词 
39         stringstream ss(sb);
40         int sum=0;//单词数 
41         while(ss>>s)
42         {
43             int sz=ma[s].size();
44             vector<pair<int,int>>vec=ma[s];
45             bool vis[105]={0};
46             for(int i=0;i<sz;i++)
47             {
48                 if(!vis[vec[i].first])//防止重复加 
49                 {
50                     cs[vec[i].first]++;//出现了加 
51                     vis[vec[i].first]=true;
52                 }
53             }
54             sum++;
55         }
56         int K=0;
57         for(int i=1;i<=T;i++)//文件i出现sum次单词 
58             if(cs[i]==sum)
59                 K++;
60         cout<<K<<
;
61         if(!K)
62         {
63             cout<<"Not Found
";
64             continue;
65         }
66         bool z[105][105]={0};
67         vector<oo>AC;
68         stringstream sn(sb);
69         while(sn>>s)
70         {
71             int sz=ma[s].size();
72             vector<pair<int,int>>vec=ma[s];
73             for(int i=0;i<sz;i++)
74             {
75                 if(cs[vec[i].first]==sum&&!z[vec[i].first][vec[i].second])//刚好出现sum次,防止重复 
76                 {
77                     //printf("%d %d
",vec[i].first,vec[i].second);
78                     z[vec[i].first][vec[i].second]=true;
79                     AC.push_back({ans[vec[i].first][vec[i].second],vec[i].first,vec[i].second});
80                 }
81             }
82         }
83         bool out[105]={0};
84         sort(AC.begin(),AC.end());//按照文件顺序和位置排序 
85         for(int i=0;i<AC.size();i++)
86         {
87             oo A=AC[i];
88             if(!out[A.I])
89             {
90                 out[A.I]=true;
91                 cout<<ans[A.I][0]<<
;
92             }
93             cout<<A.out<<
;
94         }
95     }
96     return 0;
97 }
7-13 直捣黄龙 (30 分)

本题是一部战争大片 —— 你需要从己方大本营出发,一路攻城略地杀到敌方大本营。首先时间就是生命,所以你必须选择合适的路径,以最快的速度占领敌方大本营。当这样的路径不唯一时,要求选择可以沿途解放最多城镇的路径。若这样的路径也不唯一,则选择可以有效杀伤最多敌军的路径。

输入格式:

输入第一行给出2个正整数N,城镇总数)和K(城镇间道路条数),以及己方大本营和敌方大本营的代号。随后N-1行,每行给出除了己方大本营外的一个城镇的代号和驻守的敌军数量,其间以空格分隔。再后面有K行,每行按格式城镇1 城镇2 距离给出两个城镇之间道路的长度。这里设每个城镇(包括双方大本营)的代号是由3个大写英文字母组成的字符串。

输出格式:

按照题目要求找到最合适的进攻路径(题目保证速度最快、解放最多、杀伤最强的路径是唯一的),并在第一行按照格式己方大本营->城镇1->...->敌方大本营输出。第二行顺序输出最快进攻路径的条数、最短进攻距离、歼敌总数,其间以1个空格分隔,行首尾不得有多余空格。

输入样例:

10 12 PAT DBY
DBY 100
PTA 20
PDS 90
PMS 40
TAP 50
ATP 200
LNN 80
LAO 30
LON 70
PAT PTA 10
PAT PMS 10
PAT ATP 20
PAT LNN 10
LNN LAO 10
LAO LON 10
LON DBY 10
PMS TAP 10
TAP DBY 10
DBY PDS 10
PDS PTA 10
DBY ATP 10

输出样例:

PAT->PTA->PDS->DBY
3 30 210

图论题,最短路输出路径,hash城市然后直接跑dijstra,考虑的比较多,需要仔细

这里统计路径数不能在dijstra里统计,因为这里dijstra里if判断的时候会多统计路径

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 
  4 map<string,int>nhash;
  5 map<int,string>rhash;
  6 vector<pair<int,int>>G[205];
  7 int n,m,val[205],pre[205],d[205],en[205],dead[205];
  8 string A,B,C,U,V;
  9 void dij(int S,int E)
 10 {
 11     memset(pre,-1,sizeof pre);
 12     memset(d,0x3f,sizeof d);
 13     queue<int>q;
 14     q.push(S);
 15     d[S]=0;
 16     while(!q.empty())
 17     {
 18         int u=q.front();q.pop();
 19         for(int i=0;i<G[u].size();i++)
 20         {
 21             int v=G[u][i].first;
 22             int w=G[u][i].second;
 23             if(d[v]>d[u]+w)
 24             {
 25                 d[v]=d[u]+w;
 26                 pre[v]=u;
 27                 en[v]=en[u]+val[v];
 28                 dead[v]=dead[u]+1;
 29                 q.push(v);
 30             }
 31             else if(d[v]==d[u]+w&&dead[v]<dead[u]+1)
 32             {
 33                 pre[v]=u;
 34                 en[v]=en[u]+val[v];
 35                 dead[v]=dead[u]+1;
 36                 q.push(v);
 37             }
 38             else if(d[v]==d[u]+w&&dead[v]==dead[u]+1&&en[v]<en[u]+val[v])
 39             {
 40                 pre[v]=u;
 41                 en[v]=en[u]+val[v];
 42                 q.push(v);
 43             }
 44         }
 45     }
 46 }
 47 int sum,vis[205];
 48 void dfs(int u)
 49 {
 50     if(u==nhash[B])
 51     {
 52         sum++;
 53         return;
 54     }
 55     for(int i=0;i<G[u].size();i++)
 56     {
 57         int v=G[u][i].first;
 58         int w=G[u][i].second;
 59         if(!vis[v]&&d[u]+w==d[v])
 60         {
 61             vis[v]=1;
 62             dfs(v);
 63             vis[v]=0;
 64         }
 65     }
 66 }
 67 int main()
 68 {
 69     cin>>n>>m>>A>>B;
 70     nhash[A]=n;
 71     rhash[n]=A;
 72     for(int i=1;i<n;i++)
 73     {
 74         cin>>C>>val[i];
 75         nhash[C]=i;
 76         rhash[i]=C;
 77     }
 78     for(int i=0,w;i<m;i++)
 79     {
 80         cin>>U>>V>>w;
 81         G[nhash[U]].push_back({nhash[V],w});
 82         G[nhash[V]].push_back({nhash[U],w});
 83     }
 84     dij(nhash[A],nhash[B]);
 85     dfs(nhash[A]);
 86     int pos=nhash[B];
 87     vector<int>road;
 88     while(pos!=-1)
 89     {
 90         road.push_back(pos);
 91         pos=pre[pos];
 92     }
 93     cout<<rhash[road[(int)road.size()-1]];
 94     for(int i=(int)road.size()-2;i>=0;i--)
 95         cout<<"->"<<rhash[road[i]];
 96     printf("
%d %d %d
",sum,d[nhash[B]],en[nhash[B]]);
 97     return 0;
 98 }
 99 /*
100 4 3 d a
101 a 1
102 b 2
103 c 3
104 d c 10
105 c b 10
106 b a 10
107 */
7-14 拯救007(升级版) (30 分)

在老电影“007之生死关头”(Live and Let Die)中有一个情节,007被毒贩抓到一个鳄鱼池中心的小岛上,他用了一种极为大胆的方法逃脱 —— 直接踩着池子里一系列鳄鱼的大脑袋跳上岸去!(据说当年替身演员被最后一条鳄鱼咬住了脚,幸好穿的是特别加厚的靴子才逃过一劫。)

设鳄鱼池是长宽为100米的方形,中心坐标为 (0, 0),且东北角坐标为 (50, 50)。池心岛是以 (0, 0) 为圆心、直径15米的圆。给定池中分布的鳄鱼的坐标、以及007一次能跳跃的最大距离,你需要给他指一条最短的逃生路径 —— 所谓“最短”是指007要跳跃的步数最少。

输入格式:

首先第一行给出两个正整数:鳄鱼数量 N(<=100)和007一次能跳跃的最大距离 D。随后 N 行,每行给出一条鳄鱼的 (x,y)坐标。注意:不会有两条鳄鱼待在同一个点上。

输出格式:

如果007有可能逃脱,首先在第一行输出007需要跳跃的最少步数,然后从第二行起,每行给出从池心岛到岸边每一步要跳到的鳄鱼的坐标ss

输入样例 1:

17 15
10 -21
10 21
-40 10
30 -50
20 40
35 10
0 -10
-25 22
40 -40
-30 30
-10 22
0 11
25 21
25 10
10 10
10 35
-30 10

输出样例 1:

4
0 11
10 21
10 35

输入样例 2:

4 13
-12 12
12 12
-12 -12
12 -12

输出样例 2:

0

图论题,直径15,如果能跳42.5那么可以直接跳出去

按照两点间的距离建图,然后每个点里岛的距离计算一下

然后枚举每个点开始跳,跑dijstra的同时记录路径,遇到小的更新

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 struct p
 5 {
 6     int x,y;
 7 }a[105];
 8 int n,pre[105],minstep=1e9;
 9 double D;
10 double d[105][105];
11 int st[105];
12 int ok(int x)
13 {
14     if(a[x].x-D<=-50||a[x].x+D>=50||a[x].y-D<=-50||a[x].y+D>=50)return 1;
15     return 0;
16 }
17 int dij(int S)
18 {
19     memset(pre,-1,sizeof pre);
20     memset(st,0x3f,sizeof st);
21     queue<int>q;
22     q.push(S);
23     st[S]=0;
24     while(!q.empty())
25     {
26         int u=q.front();q.pop();
27         if(ok(u))return u;
28         for(int i=0;i<n;i++)
29         {
30             if(d[u][i]<=D&&st[i]>st[u]+1)
31             {
32                 st[i]=st[u]+1;
33                 pre[i]=u;
34                 q.push(i);
35             }
36         }
37     }
38     return -1;
39 }
40 int main()
41 {
42     cin>>n>>D;
43     for(int i=0;i<n;i++)
44         cin>>a[i].x>>a[i].y;
45     if(D>=42.5)
46     {
47         cout<<"1
";
48         return 0;
49     }
50     a[n].x=a[n].y=0;
51     for(int i=0;i<n;i++)
52         for(int j=i+1;j<n;j++)
53             d[i][j]=d[j][i]=sqrt((1.*a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));
54     for(int i=0;i<n;i++)
55         d[n][i]=d[i][n]=sqrt(1.*a[i].x*a[i].x+a[i].y*a[i].y)-7.5;
56     vector<int>road;
57     double minn=1e18;
58     for(int i=0;i<n;i++)
59     {
60         if(d[n][i]<=D)
61         {
62             int E=dij(i);
63             if(E==-1)continue;
64             if((st[E]==minstep&&minn<=d[n][i])||(st[E]>minstep))continue;
65             minstep=st[E];
66             minn=d[n][i];
67             road.clear();
68             int pos=E;
69             while(pos!=-1)
70             {
71                 road.push_back(pos);
72                 pos=pre[pos];
73             }
74         }
75     }
76     printf("%d
",(int)road.size()==0?0:(int)road.size()+1);
77     for(int i=(int)road.size()-1;i>=0;i--)
78     {
79         int x=road[i];
80         printf("%d %d
",a[x].x,a[x].y);
81     }
82     return 0;
83 }
84 /*
85 3 30
86 5 0
87 27 0
88 -30 0
89 */


以上是关于2019天梯赛第三次训练赛的主要内容,如果未能解决你的问题,请参考以下文章

Contest1593 - 2018-2019赛季多校联合新生训练赛第三场(部分题解)

2018年第四阶段组队训练赛第三场(BAPC2017 Preliminaries)

UPC2018组队训练赛第三场

Contest1657 - 2019年我能变强组队训练赛第十四场

问题 L: An Invisible Hand - (2018年第二阶段个人训练赛第三场)

2018-2019赛季多校联合新生训练赛第八场(2018/12/22)补题题解