河南第八届ACM省赛(真题训练)

 

A.挑战密室   

题目描述

R组织的特工Dr. Kong 为了寻找丢失的超体元素,不幸陷入WTO密室。Dr. Kong必须尽快找到解锁密码逃离,否则几分钟之后,WTO密室即将爆炸。

 

Dr. Kong发现密室的墙上写了许多化学方程式中。化学方程式,也称为化学反应方程式,是化学式表示物质化学反应的式子。化学方程式反映的是客观事实。因此书写化学方程式要遵守两个原则:一是必须以客观事实为基础;二是要遵守质量守恒定律。

化学方程式不仅表明了反应物、生成物和反应条件。同时,化学计量数代表了各反应物、生成物物质的量关系,通过相对分子质量或相对原子质量还可以表示各物质之间的质量关系,即各物质之间的质量比。对于气体反应物、生成物,还可以直接通过化学计量数得出体积比。例如:2NaOH+H2SO4=Na2SO4+2H2O

 

经过多次试探、推理,Dr. Kong发现密码是4位数字,就隐藏在化学方程式等号后的第一个分子中,其分子量就可能是密码(若分子量不足4位,前面加0)。

好在Dr. Kong还记得墙上各化学方程式用到的化学元素的原子量如下:

 

N

C

O

Cl

S

H

Al

Ca

Zn

Na

14

12

16

35

32

2

27

40

65

23

 

你能帮Dr. Kong尽快找到密码吗?

约束条件

2≤K≤8  ,化学方程式的长度不超过50, 所有原子,分子的数量不超过9.小括号最多一层. 

输入格式

第一行:     表示有K个化学方程式;

接下来有K行,每行为一个化学方程式

输出格式

对于每个化学方程式输出一行:即密码。

Sample Input

 

32C+O2=2CO2

NaOH+H2SO4=Na2SO4+2H2O

Ca2CO3+H2O=Ca2(OH)2+CO2

Sample Output

 

0056

0142

0116

 

 

思路:模拟,思路异常清晰的栈模拟,可惜太紧张磕了很久,还心态崩了,导致根本不想敲。(模拟只能过样例555)

代码如下:

 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
string s[10]={"N","C","O","Cl","S","H","Al","Ca","Zn","Na"};
int no[10]={14,12,16,35,32,2,27,40,65,23};
int N1[10],N2[10];
int fun(int n)
{
    int ans=1;
    while(n>9)
    {
        n/=10;
        ans++;
    }
    return ans;
}
int main()
{
    int T;
    char ch;
    cin>>T;
    while(T--)
    {
        int ans=0;
        memset(N1,0,sizeof(N1));
        string M;
        bool flag=0;
        while((ch=getchar())!='=');
        while((ch=getchar())!=EOF)
        {
            if(ch=='\n')break;
            else if(ch=='+')flag=1;
            if(flag==0)M+=ch;
        }
        int Ti=1,i=0;
        if(M[i]>='0'&&M[i]<='9')
            Ti=M[i]-'0';
        while(M[i+1]>='0'&&M[i+1]<='9')
            Ti=Ti*10+M[++i]-'0';
        if(i)i++;
        for(;i<M.length();i++)
        {
            string t;
            int nu=0;
            if(M[i]=='(')
            {
                i++;
                memset(N2,0,sizeof(N2));
                while(M[i]!=')')
                {
                    nu=0;
                    if(M[i]>='A'&&M[i]<='Z')
                        t=M[i];
                    if(M[i+1]>='a'&&M[i+1]<='z')
                        t+=M[++i];
                    if(M[i+1]>='0'&&M[i+1]<='9')
                        nu=M[++i]-'0';
                    while(M[i+1]>='0'&&M[i+1]<='9')
                        nu=nu*10+M[++i]-'0';
                    for(int j=0;j<10;j++)
                    {
                        if(s[j]==t)
                        {
                            if(!nu)nu++;
                            N2[j]+=nu;
                            break;
                        }
                    }
                    i++;
                }
                if(M[i+1]>='0'&&M[i+1]<='9')
                    nu=M[++i]-'0';
                while(M[i+1]>='0'&&M[i+1]<='9')
                    nu=nu*10+M[++i]-'0';
                for(int j=0;j<10;j++)
                {
                    N2[j]*=nu;
                    ans+=N2[j]*no[j];
                }
            }
            else
            {
                nu=0;
                if(M[i]>='A'&&M[i]<='Z')
                    t=M[i];
                if(M[i+1]>='a'&&M[i+1]<='z')
                    t+=M[++i];
                if(M[i+1]>='0'&&M[i+1]<='9')
                    nu=M[++i]-'0';
                while(M[i+1]>='0'&&M[i+1]<='9')
                    nu=nu*10+M[++i]-'0';
                for(int j=0;j<10;j++)
                {
                    if(s[j]==t)
                    {
                        if(!nu)nu++;
                        N1[j]+=nu;
                        break;
                    }
                }
            }
        }
        for(int j=0;j<10;j++)
            ans+=N1[j]*no[j];
        ans*=Ti;
        int y=fun(ans);
        for(int i=0;i<4-y;i++)
            cout<<'0';
        cout<<ans<<endl;
    }
    return 0;
}

 

 

B.最大岛屿    

题目描述

   神秘的海洋,惊险的探险之路,打捞海底宝藏,激烈的海战,海盗劫富等等。加勒比海盗,你知道吧?杰克船长驾驶着自己的的战船黑珍珠1号要征服各个海岛的海盜,最后成为海盗王。  这是一个由海洋、岛屿和海盗组成的危险世界。面对危险重重的海洋与诡谲的对手,如何凭借智慧与运气,建立起一个强大的海盗帝国。

杰克船长手头有一张整个海域的海图,上面密密麻麻分布着各个海屿的位置及面积。他想尽快知道整个海域共有多少岛屿以及最大岛屿的面积。

约束条件

     ①若一个陆地八个方向之一(上、下、左、右、左上、右上、左下、右下)的位置也是陆地,则视为同一个岛屿。

② 假设第一行,最后一行,第一列,最后一列全为0.

③ 1<M, N≤500   1<T≤100000

输入格式

第1行:     M  N  T      表示海域的长,宽及一个单位表示的面积大小

接下来有M行 ,每行有N个01组成的序列以及其中穿插一些空格。0表示海水,1表示陆地,其中的空格没用,可以忽略掉。

输出格式

输出一行,有2个整数,一个空格间隔,表示整个海域的岛屿数,以及最大岛屿的面积

Sample Input

 

8 16 99

00000000 00000000

0000110011000000

0001111000111000

0000000 00 0000000

00111 111000001 10

001110000 0000000

0100001111 111100

0000000000000000

Sample Output

5 990

思路:搜索水题,用bfs或者dfs都可以,需要注意读入地图时的空格处理。

代码如下:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string>
#include<string.h>
#include<queue>
using namespace std;
int p[505][505],m,n,t,z,maxn=0;
int f[8][2]={{1,0},{-1,0},{1,1},{1,-1},{0,1},{0,-1},{-1,-1},{-1,1}};//可走的八个方位
void dfs(int x,int y,int z)
{
    maxn=max(maxn,z);//更新最大岛屿面积
    //printf("%d*",z);
    p[x][y]=0;
    for(int i=0;i<8;i++)
    {
        int x1=x+f[i][0];
        int y1=y+f[i][1];
        if(p[x1][y1]==1&&x1>=0&&y1>=0&&x1<m&&y1<n)
        {
            z++;
            dfs(x1,y1,z);
        }
    }
}
int main()
{
    int i=0,j=0,s;
    scanf("%d%d%d",&m,&n,&t);
    char ch;
    while(scanf("%c",&ch)!=EOF)
    {
        if(i==m-1&&j==n-1)
        {
            break;
        }
        if(j==n)
        {
            j=0;i++;
        }
        if(ch=='0'||ch=='1')
        {
            p[i][j]=ch-'0';j++;
            //printf("%d*",j);
        }
    }
    for(i=0;i<m;i++)
    {
        for(j=0;j<n;j++)
        {
            if(p[i][j]==1)
            {
                s++;//岛屿数增加
                z=1;
                dfs(i,j,z);
            }
        }
    }
    printf("%d %d",s,maxn*t);
    return 0;
}

 

C.最少换乘     

题目描述

    欧洲某城是一个著名的旅游胜地,每年都有成千上万的人前来观光旅行。Dr. Kong决定利用暑假好好游览一番。。

年轻人旅游不怕辛苦,不怕劳累,只要费用低就行。但Dr. Kong年过半百,他希望乘坐BUS从住的宾馆到想去游览的景点,期间尽可量地少换乘车。

 

Dr. Kon买了一张旅游地图。他发现,市政部门为了方便游客,在各个旅游景点及宾馆,饭店等地方都设置了一些公交站并开通了一些单程线路。每条单程线路从某个公交站出发,依次途经若干个站,最终到达终点站。

但遗憾的是,从他住的宾馆所在站出发,有的景点可以直达,有的景点不能直达,则他可能要先乘某路BUS坐上几站,再下来换乘同一站的另一路BUS, 这样须经过几次换乘后才能到达要去的景点。

 

为了方便,假设对该城的所有公交站用1,2,……,N编号。Dr. Kong所在位置的编号为1,他将要去的景点编号为N。

请你帮助Dr. Kong寻找一个最优乘车方案,从住处到景点,中间换车的次数最少。

 

输入格式

    第一行:     K              表示有多少组测试数据。(2≤k≤8)

接下来对每组测试数据:

第1行:       M  N        表示有M条单程公交线路,共有N站。(1<=M<=100 1<N<=500)

第2~M+1行: 每行描述一路公交线路信息,从左至右按运行顺序依次给出了该线路上的所有站号,相邻两个站号之间用一个空格隔开。

输出格式


对于每组测试数据,输出一行,如果无法乘坐任何线路从住处到达景点,则输出"N0",否则输出最少换车次数,输出0表示不需换车可以直达。

 

Sample Input

 

2

3 7

6 7

4 7 3 6

2 1 3 5

2 6

1 3 5

2 6 4 3

Sample Output

 

2

NO

 思路:将每条路相邻两点转换为边权为1的图,问题就转化为求最短路问题,但在处理时需要注意空格。需要有想法,有勇气尝试。(反正试试又不要钱

代码如下:

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#define inf 0x3f3f3f
using namespace std;
int s[1005],ma[1005][1005],dis[1005],vis[1005];
char a[1005];
int main()
{
   int t;
   scanf("%d",&t);
   while(t--)
   {
       int n,m;
       int p=0;
       scanf("%d%d",&n,&m);
       getchar();
       memset(ma,inf,sizeof(ma));
       memset(vis,0,sizeof(vis));
       memset(dis,inf,sizeof(dis));
       for(int i=1;i<=m;i++)
       {
           ma[i][i]=0;
       }
       for(int i=1;i<=n;i++)
       {
           gets(a);
           p=0;
           memset(s,0,sizeof(s));
           for(int j=0;j<strlen(a);j++)
           {
               if(a[j]!=' ')
               {
                   int sum=0;
                   while(a[j]!=' '&&j<strlen(a))
                   {
                       sum=sum*10+a[j]-'0';
                       j++;
                   }
                   s[p++]=sum;
               }
           }
           for(int k=0;k<p;k++)
           {
               for(int h=k+1;h<p;h++)
               {
                   ma[s[k]][s[h]]=1;
               }
           }
       }
      /* for(int i=0;i<10;i++)
       printf("%d ",s[i]);
       printf("\n");*/
       for(int i=1;i<=m;i++)
       {
           dis[i]=ma[1][i];
       }
       vis[1]=1;
       for(int i=1;i<m;i++)
       {
           int minn=inf,u;
           for(int j=1;j<=m;j++)
           {
               if(dis[j]<minn&&!vis[j])
               {
                   u=j,minn=dis[j];
               }
           }
           vis[u]=1;
           for(int j=1;j<=m;j++)
           {
               if(dis[j]>minn+ma[u][j]&&ma[u][j]<inf)
               {
                   dis[j]=minn+ma[u][j];
               }
           }
       }
       if(dis[m]>=inf)
        printf("NO\n");
       else
       printf("%d\n",dis[m]-1);
   }
   return 0;
}

 

D.引水工程     

题目描述


南水北调工程是优化水资源配置、促进区域协调发展的基础性工程,是新中国成立以来投资额最大、涉及面最广的战略性工程,事关中华民族长远发展。 “南水北调工程”,旨在缓解中国华北西北地区水资源短缺的国家战略性工程。就是把中国长江流域丰盈的水资源抽调一部分送到华北和西北地区。我国南涝北旱,南水北调工程通过跨流域的水资源合理配置,促进南北方经济、社会与人口、资源、环境的协调发展。

整个工程分东线、中线、西线三条调水线。东线工程位于东部,因地势低需抽水北送至华北地区。中线工程从汉水与其最大支流丹江交汇处的丹江口水库引水,自流供水给黄淮海平原大部分地区,20多座大中城市;西线工程在青藏高原上,由长江上游向黄河上游补水。

现在有N个区域需要建设水资源工程,它们可以自建水库解决缺水问题,也可以从已有水源的地区建立管道引水过来。当然,这些建设都需要大量投资。

你能不能给出一个优化水资源配置方案,在保证每个区域都能用上水的前提下,使得整个引水工程费用最低。

约束条件

2≤k≤10      1≤N≤200    1≤Wi  Pij≤100000    Pij = Pji   Pii=0 (i=1,…, N)

  所有数据都是整数。 数据之间有一个空格。

输入格式

 

第一行:     K           表示有多少组测试数据。

接下来对每组测试数据:

第1行:      N               表示有N个区域( 1<=N<=300 )

第2 行:    W1  W2  …. WN  Wi表示第i个区域自建水库需要的费用

再有N行:   Pi1  Pi2   ….  Pin   Pij表示建立第i个区域与第j个区域引水管道的费用

输出格式

对于每组测试数据,输出占一行,即建立整个引水工程的最小费用。

Sample Input

 

1

5

5 4 4 3 6

0 2 2 2 2

2 0 3 3 3

2 3 0 4 5

2 3 4 0 1

2 3 5 1 0

Sample Output

10

思路:最小生成树的模板题,用prim算法或kruskal算法均可。我采用的是prim算法

代码如下:

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<string>
#include<queue>
using namespace std;
#define maxv 1000
#define inf 1000000000
int n,G[maxv][maxv]; 
int d[maxv];
bool vis[maxv]={false};
int prim()
{
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        int u=-1,min=inf;
        for(int j=1;j<=n;j++)
        {
            if(vis[j]==false&&d[j]<min)
            {
                u=j;
                min=d[j];
            }
         } 
         if(u==-1)
         {
            return -1;
         }
         vis[u]=true;
         ans+=d[u];
         for(int v=1;v<=n;v++)
         {
            if(vis[v]==false&&G[u][v]!=inf&&G[u][v]<d[v])
            {
                d[v]=G[u][v];
             }
         }
    }
    return ans;
}
int main()
{
    int k;
    scanf("%d",&k);
    while(k--)
    {
       memset(G,0,sizeof(G));
       memset(d,0,sizeof(d));
       memset(vis,0,sizeof(vis));
    scanf("%d",&n);
    fill(d,d+maxv,inf);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&d[i]);
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&G[i][j]);
        }
    }
    /*for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            printf("%d ",G[i][j]);
        }printf("\n");
    }*/
    printf("%d\n",prim());
    //for(int i=1;i<=n;i++)printf("%d*",d[i]);printf("\n");
    }
    return 0;
}

 

E.疫情控制     

题目描述

 

据某省水产部门通报,A市大面积范围水产养殖区爆发ADH氏菌疫情,导致大量鱼苗死亡,养殖户经济损失巨大。必须尽快控制疫情,使水产养殖秩序回归正常。

此次ADH氏菌疫情传染范围较大,涉及到 M 个地区。要想对某个地区I疫情进行控制,必须先控制住上游地区I-1的疫情,再对该地区监测,管理,施药才能彻底清除传染性,真正做到水体改良,水质改善。

 

不妨设M 个地区的编号1,2,…,M,首先,地区1的疫情得到控制后,才能在1天后控制地区2。类推,仅当地区i的疫情得到控制后,1天后才能去控制地区i+1;当第M个地区疫情被控制后,才算彻底控制住A市疫情。

 

如何做到早发现,早报告,早隔离,早治理,按照属地化管理原则,A市准备建立 N 个防疫中心。当一个防疫中心启用后,它可以对方圆半径 R 范围内的地区疫情加以控制,并且持续控制5天。N 个防疫中心也不是同时启动,当一个防疫中心启用5天后,才能启动另一个防疫中心。

 

启用一个防疫中心需要大量的人力,物力。请你设计一个方案,如何启用尽可能少的防疫中心就能够对A市所有疫情加以控制。

 

约束条件】  

  1≤K≤5   1 ≤M, N ≤ 100,1≤ R≤1000,    0≤所有坐标X,Y≤10000

  所有数据都是整数。 数据之间有一个空格。

输入格式

第一行: K      表示有多少组测试数据。

接下来对每组测试数据:

第1行:      M  N  R        

第2~M+1行: X1i  Y1i       表示第 i 地区所在的坐标 i=1,…,M

第M+2~M+N+1行:     X2 j  Y2j    表示第 j 防疫中心的坐标 j=1,…,N

 

输出格式

对于每组测试数据,输出占一行:最少启用的防疫中心数量

Sample Input

 

1

4 3 6

0 6

6 6

6 0

0 0

0 3

1 1

1 5

Sample Output

2

HINT

启用3号防疫中心可以控制地区1,2

启用2号防疫中心可以控制地区3,4

思路:可能是贪心,抱歉,实在是菜,暂时不会,会了就回来补

F. Distribution   

题目描述

 

One day , Wang and Dong in the Dubai desert expedition, discovered an ancient castle. Fortunately, they found a map of the castle.The map marks the location of treasures.

They agreed to distribute the treasures according to the following rules:

 

Wang draws a horizontal line on the map and then Dong draws a vertical one so that the map is divided into 4 parts, as show below.   

Wang will save the treasures in I and III ,while those situated in II and IV will be taken away by Dong. Wang first draw a horizontal line, Dong after the draw a vertical line.

They drew several pairs of  lines. For each pair, Wang wants to know the difference between their treasures.

It's guaranteed that all the reasures will lie on neither of the lines drew by them.

输入格式

the first line contains two integers N and M, where N is the number of treasures on the map and M indicates how many times they are going to draw the lines. The 2nd to (N+1)-th lines Xi, Yi contain the co-ordinates of the treasures and the last M lines consist of the M pairs integers (X, Y) which means that the two splitting lines intersect at point (X, Y).

(  0 < NM ≤ 100,  0 ≤ Xi, Yi, X,Y ≤ 1000  )

输出格式

Output  contains  M  lines , a single line with a integer , the difference described above.

Sample Input

 

10 3

29 22

17 14

18 23

3 15

6 28

30 27

4 12

6 7

8 0

11 21

2 25

5 10

19 24

Sample Output

 

-6

4

4

思路:看懂了就是水题,很水;

代码如下:

#include<iostream>
#include<cstdio>
using namespace std;
int x[105],y[105];
int main()
{
    int n,m,c1,c2;
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)
    {
        scanf("%d%d",&x[i],&y[i]);
    }
    while(m--)
    {
        scanf("%d%d",&c1,&c2);
        int wa=0,do1=0;
        for(int i=0;i<n;i++)
        {
            if(x[i]<c1&&y[i]>c2||x[i]>c1&&y[i]<c2) wa++;
            else do1++;
        }
        /*printf("wa:%d\n",wa);
        printf("do:%d\n",do1);
        */
        printf("%d\n",do1-wa);
    }
    return 0;
}

 

G. Interference Signal   

题目描述

 

Dr.Kong’s laboratory monitor some interference signals. The interference signals can be digitized into a series of positive integer. May be, there are N integers a1,a2,…,an.

 

Dr.Kong wants to know the average strength of a contiguous interference signal block. the block must contain at least M integers.

 

Please help Dr.Kong to calculate the maximum average strength, given the constraint.

 

输入格式

The input contains K test cases. Each test case specifies:

* Line 1: Two space-separated integers, N and M.

* Lines2~line N+1:  ai  (i=1,2,,N)

1 ≤ K≤ 8,  5 ≤ N≤ 2000,   1 ≤ M ≤ N,  0 ≤ ai ≤9999

     

输出格式

For each test case generate a single line containing a single integer that is 1000 times the maximal average value. Do not perform rounding.

 

Sample Input

 

2

10 6

6

4

2

1

0

3

8

5

9

4

1

5 2

10

3

8

5

9

Sample Output

 

6500

7333

思路:如果这道题的数据范围多开个10的几次方,可能会卡在优化问题(烧脑)。但因为数据较小,使用暴力直接过。

代码如下:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<queue>
#include<string.h>
#include<string>
using namespace std;
int p[2005];
int maxn=0;
int main()
{
    int n,m,k,i,j;
    scanf("%d",&k);
    while(k--)
    {
        int z=0,maxn=0;
        scanf("%d%d",&n,&m);
        for(i=0;i<n;i++)
        {
            scanf("%d",&p[i]);
        }
        while(m!=n)
        {
            int s;
            for(i=0;i<=n-m;i++)
            {
                s=0;
                for(j=i;j<i+m;j++)
                {
                    s=s+p[j];
                }
                double z=(s*1000.00)/(m*1.00);
                maxn=max(maxn,(int)z);
            }
            m++;
        }
        printf("%d\n",maxn);
    }
    return 0;
}

 

H. Radition Protection Wall   

题目描述

A military base in the tested nuclear weapons, an explosion because of failure. In order to prevent nuclear radiation leakage,  it is necessary to establish  a closed house.

 

The closed house  is a convex polygon in the wall,  will be constructed of  N or fewer connected straight wall segments (3 <= N <=100),  forming a polygon  which contains  the location of the nuclear leak (X0,Y0).  

 

Due to the complex terrain of the military base and the cost , the chief has obtained from his contractor  a list of prices for building wall segments at various locations. He could potentially build N different wall segments, and he knows the coordinates of the endpoints and cost for each of these segments.  The location of the nuclear leak does not lie on any endpoints (X,Y) coordinates between -10000 and 10000,  and  does not lie directly on any of the potential wall segments.  

 

Determine the minimum-cost set of wall segments that forms a convex polygon containing the location of the nuclear leak.

                                

输入格式

The input contains K  test cases (1<=K<=5).  Each test case specifies:

* Line 1:       N  X0  Y0 

* Lines 2..N+1:  Five space-separated integers describing a potential wall segment.  

the first two integers are the X and Y,coordinates of one endpoint;

the next two integers are the X and Y coordinates of the second endpoint;  the last integer is the cost C of building that wall (1 <= C <= 10000).

输出格式

For each test case generate a single line containing a single integer that is the cost of the cheapest set of walls which form a legal prison or -1 if no such prison can be constructed

Sample Input

 

1

8 1 1

0 0 0 3 2

0 0 3 1 2

3 1 2 3 2

0 3 1 2 1

1 2 2 3 1

0 3 2 3 4

1 2 0 0 8

3 1 0 3 8

Sample Output

10

HINT

Use the first, second, third, and sixth walls.

小白水平有限,该题没读懂,不怎么会。

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <string>
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MAXN (100+10)
#define MAXM (500000)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
#define PI acos(-1.0)
using namespace std;
struct Point{
    int x, y;
    Point(){};
    Point(int X, int Y){
        x = X; y = Y;
    }
};
Point operator - (Point A, Point B){
    return Point(A.x-B.x, A.y-B.y);
}
bool operator == (Point A, Point B){
    return A.x == B.x && A.y == B.y;
}
int Cross(Point A, Point B){
    return A.x*B.y - A.y*B.x;
}
int Dot(Point A, Point B){
    return A.x*A.y - B.x*B.y;
}
struct Line{
    Point s, e;
    int cost;
    Line(){};
    Line(Point A, Point B){
        s = A; e = B;
    }
};
Line L[MAXN];
int Map[MAXN][MAXN], dist[MAXN];
bool vis[MAXN];
int dijkstra(int s, int e, int n)
{
    for(int i = 0; i < n; i++)
    {
        dist[i] = Map[s][i];
        vis[i] = false;
    }
    //vis[s] = true;
    for(int i = 1; i < n; i++)
    {
        int Min = INF, next = i;
        for(int j = 0; j < n; j++)
        {
            if(!vis[j] && Min > dist[j])
            {
                Min = dist[j];
                next = j;
            }
        }
        vis[next] = true;
        for(int j = 0; j < n; j++)
            if(!vis[j])
                dist[j] = min(dist[j], Map[next][j] + dist[next]);
    }
    return dist[e];
}
bool judge(Line A, Line B, Point P)
{
    if(Cross(A.e-A.s, B.s-A.s) == 0 && Cross(A.e-A.s, B.e-A.s) == 0)//一条线段被另一条线段包含 不处理
    {
        if(min(A.s.x, A.e.x) >= min(B.s.x, B.e.x) && max(A.s.x, A.e.x) <= max(B.s.x, B.e.x)
        || min(B.s.x, B.e.x) >= min(A.s.x, A.e.x) && max(B.s.x, B.e.x) <= max(A.s.x, A.e.x))
            return false;
    }
    if(A.s == B.s)
    {
        if(Cross(A.s-A.e, B.e-B.s) >= 0 && Cross(B.e-B.s, P-B.e) > 0)
            return true;
    }
    if(A.s == B.e)
    {
        if(Cross(A.s-A.e, B.s-B.e) >= 0 && Cross(B.s-B.e, P-B.s) > 0)
            return true;
    }
    if(A.e == B.s)
    {
        if(Cross(A.e-A.s, B.e-B.s) >= 0 && Cross(B.e-B.s, P-B.e) > 0)
            return true;
    }
    if(A.e == B.e)
    {
        if(Cross(A.e-A.s, B.s-B.e) >= 0 && Cross(B.s-B.e, P-B.s) > 0)
            return true;
    }
    return false;
}
bool OnSegment(Point P, Line A){
    return Cross(A.s-P, A.e-P) == 0 && Dot(A.s-P, A.e-P) <= 0;
}
int main()
{
    int t; Ri(t);
    W(t)
    {
        int n, x0, y0; Ri(n); Ri(x0); Ri(y0);
        Point P = Point(x0, y0);
        for(int i = 0; i < n; i++)
        {
            Ri(L[i].s.x); Ri(L[i].s.y);
            Ri(L[i].e.x); Ri(L[i].e.y);
            Ri(L[i].cost);
        }
        CLR(Map, INF);
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < n; j++)
            {
                if((L[i].s == L[j].s && L[i].e == L[j].e) || (L[i].s == L[j].e && L[i].e == L[j].s)) continue;
                if(judge(L[i], L[j], P))
                    Map[i][j] = min(Map[i][j], L[j].cost);
            }
        }
        int ans = INF;
        for(int i = 0; i < n; i++)
            ans = min(ans, dijkstra(i, i, n));
        if(ans == INF)
            Pi(-1);
        else
            Pi(ans);
    }
    return 0;
}

总结:题不是很难,但模拟赛时却是惨败,其最终原因还是因为自己太菜,心态也不好,已经多次出现心态一崩就不想敲,最终全崩的情况,还需要多多努力,追上大佬们的步伐。

 

 

 

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值