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\n", 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("************\n  Welcome\n************");
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\n");
41         else printf("%05d\n",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\n");
47         else printf("%05d\n",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\n",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\n";
12             else cout<<"Not An Equation\n";
13         }
14         else if(a==0)
15         {
16             double x=-c/b;
17             if(fabs(x)<=1e-6)x=0;
18             printf("%.2f\n",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\n",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\n%.2f\n",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\n%.2f-%.2fi\n",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\n",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<<'\n';
61         if(!K)
62         {
63             cout<<"Not Found\n";
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\n",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]<<'\n';
92             }
93             cout<<A.out<<'\n';
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("\n%d %d %d\n",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\n";
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\n",(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\n",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 */


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM