同志们的毒害1_xuhang01

    在光老犇的迫害下,高二全体信奥成员 含泪  为自己的战友们出了一套题

  xuhang01同学光荣成为第一位迫害人,出了一套科学且玄学的卷,照理水一发题解博客

  链接: http://218.62.22.209:8080/contest.php?cid=2228

    T1

  二分求解,二分两棵树之间的最长距离,O(n)验证即可

  但是跑之前要先sort一遍...... 

  
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int n,m,maxx;
 4 int a[100010];
 5 bool check(int x){
 6     int now=a[1],num=0;
 7     for(register int i=2;i<=n;i++){
 8         if(abs(a[i]-now)>=x) num++,now=a[i];
 9         if(num==m-1) return true;
10     }
11     return false;
12 }
13 int ef(int l,int r){
14     if(l==r) return l;
15     int mid=(l+r)/2;
16     if(check(mid+1)) ef(mid+1,r); 
17     else ef(l,mid);
18 }
19 int main(){
20     scanf("%d%d",&n,&m);
21     for(register int i=1;i<=n;i++) scanf("%d",&a[i]),maxx=max(a[i],maxx);
22     sort(a+1,a+n+1);
23     printf("%d",ef(1,maxx));
24     return 0;
25 }
树的题

    T2

  模拟,每次插入新值时做判断,如果当前数位所放位置没被放,

更新被赋值点的赋值方向赋值,有被放过就更新所有的前后关系即可

  
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 struct node{
 4     int l,r;
 5 }a[1000010];
 6 int n,m,now=1,x,y;
 7 bool vis[1000010];
 8 int main(){
 9     scanf("%d",&n);
10     for(register int i=2;i<=n;i++){
11         scanf("%d%d",&x,&y);
12         if(y==1){
13             if(!a[x].r) a[x].r=i,a[i].l=x;
14             else if(a[x].r) a[i].l=x,a[i].r=a[x].r,a[a[x].r].l=i,a[x].r=i;
15               
16         }
17         else if(y==0){
18             if(!a[x].l) a[x].l=i,a[i].r=x;
19             if(x==now) now=i;
20             else if(a[x].l) a[i].r=x,a[i].l=a[x].l,a[a[x].l].r=i,a[x].l=i;
21         }
22     }
23     scanf("%d",&m);
24     for(register int i=1;i<=m;i++) scanf("%d",&x),vis[x]=1;
25     while(a[now].r){
26         if(!vis[now]) printf("%d ",now);
27         now=a[now].r;
28     }
29     if(!vis[now]) printf("%d",now);
30     return 0;
31 } 
开车题

    T3

  全员连边,从(0,0)开始暴力搜索即可

  
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 struct node{
 4     double x,y;
 5 }a[100010];
 6 int n,cnt;
 7 double turn(int q,int p){
 8     double emm=sqrt(((double)(a[q].x-a[p].x)*(a[q].x-a[p].x))+((double)(a[q].y-a[p].y)*(a[q].y-a[p].y)));
 9     return emm;
10 }
11 double anss=99999999;
12 double ans[20][20];
13 bool vis[20];
14 void dfs(int now,double now_ans,int num){
15     if(now_ans>anss) return;
16     if(num==n){anss=min(anss,now_ans);return;}
17     for(register int i=1;i<=n;i++){
18         if(i==now) continue;
19         if(vis[i]) continue;
20         vis[i]=1;
21         dfs(i,now_ans+ans[now][i],num+1);
22         vis[i]=0;
23     }
24 }
25 int main(){
26     scanf("%d",&n);
27     for(register int i=1;i<=n;i++){
28         scanf("%lf%lf",&a[i].x,&a[i].y);
29         for(register int j=1;j<i;j++){
30             ans[i][j]=ans[j][i]=turn(i,j);
31         }
32     }
33     a[n+1].x=0,a[n+1].y=0;
34     for(register int i=1;i<=n;i++){
35         ans[n+1][i]=ans[i][n+1]=turn(n+1,i);
36     }
37     n++;
38 //    for(register int i=1;i<=n;i++){
39 //    for(register int j=1;j<=n;j++) printf("%.2lf ",ans[i][j]);printf("\n");}
40     vis[n]=1;
41     dfs(n,0,1); 
42     printf("%.2lf",anss);
43     return 0;
44 }
JOJO

    T4

  先初始化好一个倒着的答案,占用4*4空间,然后每n++就向右复制一遍

再向下面的中间位置复制一遍,同时更新空间占用情况即可

  
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 char a[3000][3000];
 4 int n,now=4,k=1;
 5 int main(){
 6     scanf("%d",&n);
 7     memset(a,' ',sizeof(a));
 8     a[1][1]=a[2][2]='/';
 9     a[1][2]=a[1][3]='_';
10     a[1][4]=a[2][3]='\\';
11     while(k<n){
12         for(register int i=1;i<=now/2;i++)
13             for(register int j=1;j<=now;j++)
14         a[i+now/2][j+now/2]=a[i][j+now]=a[i][j];
15         now*=2,k++;
16     }
17     for(int i=now/2;i>=1;i--){
18         for(int j=1;j<=now;j++) printf("%c",a[i][j]); 
19         printf("\n");
20     }
21     return 0;
22 }
三角形

    T5

  咕咕咕.....

    T6

  输入时建边,星门对准的边边权为0,其他的边边权为1,

跑一遍最短路即可

  
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int a[110][110];
 4 int n,st,en,m,x;
 5 int maxx=99999999;
 6 int main(){
 7     scanf("%d%d%d",&n,&st,&en);
 8     for(register int i=1;i<=n;i++)
 9         for(register int j=1;j<=n;j++)
10             if(i==j) a[i][j]=0;
11             else a[i][j]=maxx;
12     for(register int i=1;i<=n;i++){
13         scanf("%d",&m);
14         for(register int j=1;j<=m;j++){
15             scanf("%d",&x);
16             if(j==1){a[i][x]=0;continue;}
17             a[i][x]=1;
18         }
19     }
20     for(register int i=1;i<=n;i++)
21     for(register int j=1;j<=n;j++)
22     for(register int k=1;k<=n;k++){
23         a[j][k]=min(a[j][k],a[j][i]+a[i][k]);
24     }
25     if(a[st][en]==maxx) printf("-1");
26     else printf("%d",a[st][en]);
27     return 0;
28 } 
星际披萨

    T7

   首先理解题意,如果能用2的k次方跑到终点答案即1,每多一个二进制

数ans++,同样我们先Floyd初始化,然后再在Floyd外层加一层,判断2进制数

的循环更新答案即可

  
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int a[110][110];
 4 bool vis[110][110][50];
 5 int n,m,x,y;
 6 int main(){
 7     memset(a,0x3f,sizeof(a));
 8     scanf("%d%d",&n,&m);
 9     for(register int i=1;i<=m;i++)  scanf("%d%d",&x,&y),a[x][y]=1,vis[x][y][0]=1;
10     for(register int i=1;i<=n;i++) a[i][i]=0;
11      
12     for(register int i=1;i<=30;i++)
13     for(register int j=1;j<=n;j++)
14     for(register int k=1;k<=n;k++)
15     for(register int g=1;g<=n;g++) if(vis[j][k][i-1]&&vis[k][g][i-1]) vis[j][g][i]=1,a[j][g]=1;
16      
17     for(register int i=1;i<=n;i++)
18     for(register int j=1;j<=n;j++)
19     for(register int k=1;k<=n;k++) a[j][k]=min(a[j][k],a[j][i]+a[i][k]);
20      
21     printf("%d",a[1][n]);
22     return 0;
23 }
星际跃迁

  end;

  

猜你喜欢

转载自www.cnblogs.com/liuhailin/p/11399999.html