2018-新生

A. I Speak Whales

Problem Description
According to Wikipedia, a Walsh matrix is a specific square matrix, with dimensions equal to a power of 2, the entries of which are +1 or -1, and the property that the dot product of any two distinct rows (or columns) is zero. Below are the first three Walsh Matrices. (The gray lines are imaginary lines for illustration purpose only.)

A Walsh Matrix of size 2N+1 can be constructed as the “union” of 4 Walsh Matrices of size 2N arranged such that the lower right matrix is inverted whereas the other 3 matrices are not, i.e.:

Let’s number the rows of a given Walsh Matrix from the top starting with row 0. Similarly, let’s number the columns of the matrix from the left starting with column 0. Given the four integers N , R , S , and E , write a program that will construct a Walsh Matrix of size 2N and will print the sum of all the numbers in row #R between columns #S and #E (inclusive.)
Input
Your program will be tested on one or more test cases. Each test case is specified using a single line listing four integers in the following order: N , R , S , and E , where 0<=N<=60 , 0<=R < 2^N , 0<=S<=E < 2^N , and E-S<=10, 000 . The last line of the input file has four -1’s and is not part of the test cases.
Output
For each test case, print the output on a single line.
Sample Input
2 1 0 1
48 0 0 47
-1 -1 -1 -1

Sample Output

0
48

题意
后面的矩阵都是是由四个前面的矩阵构成,而右下角是前面的相反矩阵。
现在求:第n个矩阵的第r行从s到t的总和是多少?

解题思路:
我们可以递归求解,边界条件就是n = 0时,返回1。
由于右上方、左下方和左上方相同,右下方是左上方的相反,所以不管查询的是哪里,我们都能把它递归到左上方的矩阵中。

#include <stdio.h>


long long base[111];

long long dfs(long long n, long long r, long long s, long long e)
{
    if (n == 0) return 1;
    long long ret = 0;
    long long num = base[n] / 2;
    if (r < num) 
    {
        if (e < num) ret = dfs(n - 1, r, s, e);
        else if (s >= num) ret = dfs(n - 1, r, s - num, e - num);
        else ret = dfs(n - 1, r, s, num - 1) + dfs(n - 1, r, 0, e - num);
    }
    else 
    {
        if (e < num) ret = dfs(n - 1, r - num, s, e);
        else if (s >= num) ret = -dfs(n - 1, r - num, s - num, e - num);
        else ret = dfs(n - 1, r - num, s, num - 1) - dfs(n - 1, r - num, 0, e - num);
    }
    return ret;

}


int main()
{
    long long n, r, s, e;
    base[0] = 1;
    for (int i = 1; i <= 60; ++i) base[i] = base[i - 1] * 2;
    while (1) 
    {
        scanf("%lld%lld%lld%lld",&n,&r,&s,&e);
        if (n == -1 && r == -1 && s == -1 && e == -1) break;
        printf("%lld\n",dfs(n,r,s,e));
    }
    return 0;
} 

B. Robberies
Problem Description
The aspiring Roy the Robber has seen a lot of American movies, and knows that the bad guys usually gets caught in the end, often because they become too greedy. He has decided to work in the lucrative business of bank robbery only for a short while, before retiring to a comfortable job at a university.

For a few months now, Roy has been assessing the security of various banks and the amount of cash they hold. He wants to make a calculated risk, and grab as much money as possible.

His mother, Ola, has decided upon a tolerable probability of getting caught. She feels that he is safe enough if the banks he robs together give a probability less than this.
Input
The first line of input gives T, the number of cases. For each scenario, the first line of input gives a floating point number P, the probability Roy needs to be below, and an integer N, the number of banks he has plans for. Then follow N lines, where line j gives an integer Mj and a floating point number Pj .
Bank j contains Mj millions, and the probability of getting caught from robbing it is Pj .
Output
For each test case, output a line with the maximum number of millions he can expect to get while the probability of getting caught is less than the limit set.
Notes and Constraints
0 < T <= 100
0.0 <= P <= 1.0
0 < N <= 100
0 < Mj <= 100
0.0 <= Pj <= 1.0
A bank goes bankrupt if it is robbed, and you may assume that all probabilities are independent as the police have very low funds.

Sample Input
3
0.04 3
1 0.02
2 0.03
3 0.05
0.06 3
2 0.03
2 0.03
3 0.05
0.10 3
1 0.03
2 0.02
3 0.05
Sample Output
2
4
6

题意:
一个小偷去抢劫银行,没个银行都有一定被捉的概率,求小偷在不被捉的情况下,能抢劫的最大金钱数。

解题思路:
此题为01背包装满问题,即背包的体积与所要装的东西的体积相等。在此题中,由于概率为浮点数,不能作为背包体积。所以,设定背包体积为金钱数,价值为概率,使概率尽可能的小。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;

double MAX(double x, double y)
{
    return x>y?x:y;
}


int main()
{
    int x,y,z,t,n;
    int money[105];
    double g[105],p,f[10000];
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lf%d",&p,&n);
        int sum = 0;
        for(x=0;x<n;x++)
        {
            scanf("%d%lf",&money[x],&g[x]);
            sum += money[x];
        }
        memset(f,0,sizeof(f));
        f[0] = 1;
        for(x=0;x<n;x++)
        {
            for(y=sum;y>=money[x];y--)
            {
                f[y] = MAX(f[y],f[y-money[x]]*(1-g[x]));
            }

        }
        for(x=sum;x>=0;x--)
        {
            if(f[x]>(1-p))
            {
                printf("%d\n",x);
                break;
            }
        }

    }
    return 0;
}

C. Alice, Bob and Chocolate

Problem Description
Alice and Bob like games. And now they are ready to start a new game. They have placed nn chocolate bars in a line. Alice starts to eat chocolate bars one by one from left to right, and Bob — from right to left. For each chocololate bar the time, needed for the player to consume it, is known (Alice and Bob eat them with equal speed). When the player consumes a chocolate bar, he immediately starts with another. It is not allowed to eat two chocolate bars at the same time, to leave the bar unfinished and to make pauses. If both players start to eat the same bar simultaneously, Bob leaves it to Alice as a true gentleman.
How many bars each of the players will consume?

Input
The first line contains one integer nn ( 1<=n<=10^5 ) — the amount of bars on the table. The second line contains a sequence t1​,t2​,…,tn​ ( 1<=ti​<=1000 ), where ti​ is the time (in seconds) needed to consume the i -th bar (in the order from left to right).
Output
Print two numbers a and b , where aa is the amount of bars consumed by Alice, and b is the amount of bars consumed by Bob.
Sample Input
5
2 9 8 2 7
Sample Output
2 3

题意:
lice和Bob吃巧克力棒,给出一堆巧克力棒,长度不一,吃巧克力棒的速度是相同且均匀的。Alice从左边的巧克力棒开始吃,Bob同时从右边吃。如果两人同时看到最后一根巧克力棒,Bob会让给Alice吃。吃完为止。输出两人吃的巧克力棒个数。

解题思路:
直接模拟两个人吃巧克力的过程。

#include<stdio.h>
int num[100002];
int main() {
    int n,p1,p2;
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
        scanf("%d",num+i);
    p1=1;   //p1记录A吃到的位置
    p2=n;   //p2记录B吃到的位置
    for(int sum1=0,sum2=0;p1<=p2;) { //模拟过程
        if(sum1<=sum2)
            sum1+=num[p1++];
        else
            sum2+=num[p2--];
    }
    printf("%d %d\n",p1-1,n-p2);    //注意输出
    return 0;
}

D.Beaver Game
第2315 题
Problem Description
Two beavers, Timur and Marsel, play the following game.
There are nn logs, each of exactly mm meters in length. The beavers move in turns. For each move a beaver chooses a log and gnaws it into some number (more than one) of equal parts, the length of each one is expressed by an integer and is no less than kk meters. Each resulting part is also a log which can be gnawed in future by any beaver. The beaver that can’t make a move loses. Thus, the other beaver wins.
Timur makes the first move. The players play in the optimal way. Determine the winner.

Input
The first line contains three integers n , m , k ( 1<=n,m,k<=10^9 ).
Output
Print “Timur”, if Timur wins, or “Marsel”, if Marsel wins. You should print everything without the quotes.
Sample Input
1 15 4
Sample Output
Timur

题意:
两只海狸(Timur and Marsel)做游戏 什么游戏呢? 有n条长度为m的木棍 从Timur开始,每只海狸轮流将一根已有的木棍任意等分 但要保证等分后的每一段长度都是不小于k的整数 (m,n,k为小于等于1000000000的正整数) 先无法等分的海狸输 已知Timur and Marsel,无比聪明,他们每一步都最优。

解题思路:
分三种情况

1.如果有偶数根木条,那就后手获胜,因为可以模仿,然后获胜了

2.如果有奇数根木条,那就要看先手的能不能把多出来的那根切没,如果能,就转化为了第一种情况,先后手翻转(两级反转),所以是先手胜

3.先手做不到,后手胜

#include<stdio.h>
#include<math.h>


bool swin(int a,int min)
{
    int k=sqrt(a)+1;
    for(register int i=1;i<k;++i)
    {
        if(a%i!=0)
        {
            continue;
        }
        if(i>=min&&a/i>1)
        {
            return 0;
        }
        else
        {
            if(i>1&&a/i>=min)
            {
                return 0;
            }
        }
    }
    return 1;
}

int main()
{
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    if(n%2==0)
    {
        printf("Marsel");
    }
    else
    {
        if(swin(m,k))
        {
             printf("Marsel");
        }
        else
        {
             printf("Timur");
        }
    }
}

E. Hexadecimal

Problem Description
One beautiful July morning a terrible thing happened in Mainframe: a mean virus Megabyte somehow got access to the memory of his not less mean sister Hexadecimal. He loaded there a huge amount of nn different natural numbers from 1 to nn to obtain total control over her energy.
But his plan failed. The reason for this was very simple: Hexadecimal didn’t perceive any information, apart from numbers written in binary format. This means that if a number in a decimal representation contained characters apart from 0 and 1, it was not stored in the memory. Now Megabyte wants to know, how many numbers were loaded successfully.

Input
Input data contains the only number n ( 1<=n<=10^9 ).
Output
Output the only number — answer to the problem.
Sample Input
10
Sample Output
2

题意:
输入n,输出1-n的自然数中各数位只包含0和1的数的个数。

解题思路:
本题要找各数位只包含0和1的数的个数。,即形式是二进制数的个数。而二进制型的数均为 n*10n∗10 或 n*10+1n∗10+1 的形式,所以我们只要找出这两种类型的数就可以了。

#include<stdio.h>
int n;
int count=0;//计数器 
int binary(int m)
 {//找出二进制型的数 
    if(m>n) 
        return 0;//超过范围及时退出 
    else 
        count++;
    binary(m*10);//找n*10型的二进制型数 
    binary(m*10+1);//找n*10+1型的二进制型数 
}
int main() 
{
    scanf("%d", &n);//输入n 
    binary(1);//从1开始找 
    printf("%d\n", count);//输出结果 
    return 0;
}

F. Jumping Jack

Problem Description
Jack is working on his jumping skills recently. Currently he’s located at point zero of the number line. He would like to get to the point x . In order to train, he has decided that he’ll first jump by only one unit, and each subsequent jump will be exactly one longer than the previous one. He can go either left or right with each jump. He wonders how many jumps he needs to reach x .
Input
The input data consists of only one integer x ( −10^9<=x<=10^9 ).
Output
Output the minimal number of jumps that Jack requires to reach x.
Sample Input
2
Sample Output
3

题意:
杰克最近正在练习他的弹跳技术。目前,他位于数轴的零点,他想到达点x。为了训练,他决定第一次跳一个单位,然后每跳一次都比前一次长。他每一次跳跃都可以向左或向右,他想知道他最少需要跳多少次才能到达点x。

解题思路:
最快的跳法是往一个方向一直跳。如果恰好能到x,这样肯定是跳跃次数最小。如果不能恰好跳到,那么我们设y为以这种跳法得到的第一个比x大的点,如果y-x为偶数,可以将第(y-x)/2步往左跳,这样就能恰好跳到x了;如果y-x为奇数,那么继续跳直到与x的差为偶数即可。

#include<stdio.h>
int main() 
{
    int x,ans=0;
    scanf("%d",&x);
    if(x<0)          //将负点转换为正点
        x=-x;
    for(int i=1,t=1;x&&!ans;++i,t+=i)   //i为跳跃次数,t为累计跳跃的距离
        if(t==x||(t>x&&!((t-x)%2)))
            ans=i;                      //符合分析中的条件便跳出循环
    printf("%d\n",ans);
    return 0;
}

G. Om Nom and Dark Park

Problem Description
Om Nom is the main character of a game “Cut the Rope”. He is a bright little monster who likes visiting friends living at the other side of the park. However the dark old parks can scare even somebody as fearless as Om Nom, so he asks you to help him.
The park consists of 2^(n+1)-1 squares connected by roads so that the scheme of the park is a full binary tree of depth nn . More formally, the entrance to the park is located at the square 11 . The exits out of the park are located at squares 2^(n),2^(n)+1,…,2^(n+1)-1 and these exits lead straight to the Om Nom friends’ houses. From each square ii ( 2<=i<2^(n+1) ) there is a road to the square( i/2). Thus, it is possible to go from the park entrance to each of the exits by walking along exactly n roads.

To light the path roads in the evening, the park keeper installed street lights along each road. The road that leads from square i to square has ai lights.Om Nom loves counting lights on the way to his friend. Om Nom is afraid of spiders who live in the park, so he doesn’t like to walk along roads that are not enough lit. What he wants is that the way to any of his friends should have in total the same number of lights. That will make him feel safe.
He asked you to help him install additional lights. Determine what minimum number of lights it is needed to additionally place on the park roads so that a path from the entrance to any exit of the park contains the same number of street lights. You may add an arbitrary number of street lights to each of the roads.

Input
The first line contains integer n ( 1<=n<=10 ) — the number of roads on the path from the entrance to any exit.
The next line contains 2^(n+1)−2 numbers (a2),(a3),… — the initial numbers of street lights on each road of the park. Here ai​ is the number of street lights on the road between squares ii and . All numbers ai​ are positive integers, not exceeding 100 .
Output
Print the minimum number of street lights that we should add to the roads of the park to make Om Nom feel safe.
Sample Input
2
1 2 3 4 5 6
Sample Output
5

题意:
一颗深度为n+1的满二叉树,根结点编号为1。现在要增加一些边的边权,使根结点到每个叶子节点所经过的边权之和相等。求增加的最小值。

解题思路:
对于一个节点到两个子节点,若两边边权不相等,则需要增加较少的一边的边权,使其相等。从而可以自下而上,依次求出两个子节点到根节点边权的差值,累加即可。
每次求出差值后,还应当将较大的边权累加到其父节点到其祖父结点的边权上,保证一致性。

#include<iostream>  
#include<stdio.h>
#include <fstream>
using namespace std;  
#define lson i<<1  
#define rson i<<1|1  
int a[1<<11];  
int main()  
{  
    int i,n,l;  
    //ifstream read ("test.txt");
    scanf("%d",&n);
    //read>>n;  
    l=(1<<(n+1))-1;  
    for(i=2;i<=l;++i) 
    scanf("%d",&a[i]);   //read>>a[i];
    int ans=0;  
    for(i=(l>>1);i>=1;--i)  
    {  
        a[i]+=max(a[lson],a[rson]);  
        ans+=abs(a[lson]-a[rson]);  
    }  
    printf("%d\n",ans);  
    return 0;  
}

H. Obsession with Robots

Problem Description
The whole world got obsessed with robots,and to keep pace with the progress, great Berland’s programmer Draude decided to build his own robot. He was working hard at the robot. He taught it to walk the shortest path from one point to another, to record all its movements, but like in many Draude’s programs, there was a bug — the robot didn’t always walk the shortest path. Fortunately, the robot recorded its own movements correctly. Now Draude wants to find out when his robot functions wrong. Heh, if Draude only remembered the map of the field, where he tested the robot, he would easily say if the robot walked in the right direction or not. But the field map was lost never to be found, that’s why he asks you to find out if there exist at least one map, where the path recorded by the robot is the shortest.
The map is an infinite checkered field, where each square is either empty, or contains an obstruction. It is also known that the robot never tries to run into the obstruction. By the recorded robot’s movements find out if there exist at least one such map, that it is possible to choose for the robot a starting square (the starting square should be empty) such that when the robot moves from this square its movements coincide with the recorded ones (the robot doesn’t run into anything, moving along empty squares only), and the path from the starting square to the end one is the shortest.
In one movement the robot can move into the square (providing there are no obstrutions in this square) that has common sides with the square the robot is currently in.
Input
The first line of the input file contains the recording of the robot’s movements. This recording is a non-empty string, consisting of uppercase Latin letters L, R, U and D, standing for movements left, right, up and down respectively. The length of the string does not exceed 100.
Output
In the first line output the only word OK (if the above described map exists), or BUG (if such a map does not exist).
Sample Input
LLUUUR

Sample Output
OK

题意:
问从起点到终点的路径是否为最短路径。

解题思路:
如果该路径为如果某路径是迷宫的最短路径,那么满足以下条件:
经过的位置最多只出现一次
走到某个位置时,这个位置只能由刚经过的位置到达,而其周围的格子没有被走过。

#include<stdio.h>
int Const[2][4]={{-1,0,1,0},{0,1,0,-1}};
char *str="URDL";
bool mark[204][204];        //标记位置是否到达过
char s[102];
int Use(char c) 
{
    for(int i=0;i<4;++i)
        if(c==str[i])
            return i;
    return -1;
}
bool Check(int x,int y) 
{       //检查是否不是最短路的函数(不是最短路返回1)
    if(mark[x][y])
        return 1;           //如果该位置已经走到过则不是最短路
    int cnt=0;              //记录该位置周围已经经过的点的数量
    for(int i,j,k=0;k<4;++k) 
    {
        i=x+Const[0][k];
        j=y+Const[1][k];
        if(mark[i][j])
            ++cnt;
    }
    return cnt>1;            //如果点的数量大于1,,则不是最短路
}
bool Solve(int x,int y)
{
    mark[x][y]=1;
    for(int i=0,t;s[i];++i)
    {       //一步一步检查
        t=Use(s[i]);
        x+=Const[0][t];
        y+=Const[1][t];
        if(Check(x,y))
            return 0;
        mark[x][y]=1;
    }
    return 1;
}
int main() 
{
    scanf("%s",s);
    printf("%s\n",Solve(101,101)? "OK":"BUG");
    return 0;
}  }
    return 1;
}
int main() {
    scanf("%s",s);
    printf("%s\n",Solve(101,101)? "OK":"BUG");
    return 0;
}

I. Jeopardy!

Problem Description
Jeopardy!’ is an intellectual game where players answer questions and earn points. Company Q conducts a simplified ‘Jeopardy!’ tournament among the best IT companies. By a lucky coincidence, the old rivals made it to the finals: company R1 and company R2.
The finals will have n questions, m of them are auction questions and n−m of them are regular questions. Each question has a price. The price of the i -th question is ai​ points. During the game the players chose the questions. At that, if the question is an auction, then the player who chose it can change the price if the number of his current pointsis strictly larger than the price of the question. The new price of the question cannot be less than the original price and cannot be greater than the current number of points of the player who chose the question. The correct answer brings the player the points equal to the price of the question. The wrong answer to the question reduces the number of the player’s points by the value of the question price.
The game will go as follows. First, the R2 company selects a question, then the questions are chosen by the one who answered the previous question correctly. If no one answered the question, then the person who chose last chooses again.
All R2 employees support their team. They want to calculate what maximum possible number of points the R2 team can get if luck is on their side during the whole game (they will always be the first to correctly answer questions). Perhaps you are not going to be surprised, but this problem was again entrusted for you to solve.
Input
The first line contains two space-separated integers n and m ( 1 <= n , m <= 100 ; m <= m i n ( n , 30 ) ) — the total number of questions and the number of auction questions, correspondingly. The second line contains nn space-separated integers a1​,a2​,…,an​ (1<=ai​<=10^7) — the prices of the questions. The third line contains mm distinct integers bi​ (1<=bi​<=n) — the numbers of auction questions. Assume that the questions are numbered from 1 to n .
Output
In the single line, print the answer to the problem — the maximum points the R2 company can get if it plays optimally well. It is guaranteed that the answer fits into the integer 64-bit signed type.
Sample Input
4 1
1 3 7 5
3
Sample Output
18

题意:
“Jeopardy!”的决赛将有n问题,每个问题都有对应的得分ai,其中有m个问题可以选择不得分,而将现有总得分翻倍。你可以安排关卡的通过顺序和策略,求最大得分。

解题思路:
这道题是可以贪心通过的一道题,具体思路是将可以翻倍关卡放在后面,且按从大到小排序,依次贪心。有一种特殊情况:n==m,即每个关卡均可以翻倍,对于这种情况,先对关卡得分降序排序,再进行处理。最大分数的关卡要选择得分而不翻倍,后面的关卡选择翻倍而不得分,这样处理最优。

#include<iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
int n,m;
long long ans=0;
struct numbe
{
    int a;
    bool b;
}num[105];
bool cmp(numbe a,numbe b)
{
    if(a.b==b.b)//如果两者皆可翻倍或皆可不翻倍,则应按得分降序排列。
        return a.a>b.a;
    else//不可翻倍的关卡应放在最前以便于后面翻倍
        return a.b<b.b;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&num[i].a);
    }
    for(int i=1,w;i<=m;i++)
    {
        scanf("%d",&w);
        num[w].b=1;
    }
    sort(num+1,num+n+1,cmp);
    if(n!=m)//一般情况
        for(int i=1;i<=n;i++)
        {
            if(!num[i].b)ans+=num[i].a;//不翻倍则得分
            else ans+=max((long long)num[i].a,ans);//若翻倍得分比不翻倍而得关卡分得分小,则得题目分,否则得翻倍分。
        }
    else//n==m的特殊情况
    {
        ans=num[1].a;//在排序后,最大分数的关卡得分而不翻倍,后面的关卡选择翻倍最优。因为无论怎么翻倍都不会比此关卡得分翻倍得分大。
        for(int i=1;i<n;i++)
        {
            ans*=2;
        }
    }
    printf("%lld\n",ans);
    return 0;
}

J. Ancient Berland Circus

Problem Description
Nowadays all circuses in Berland have a round arena with diameter 13 meters, but in the past things were different.
In Ancient Berland arenas in circuses were shaped as a regular (equiangular) polygon, the size and the number of angles could vary from one circus to another. In each corner of the arena there was a special pillar, and the rope strung between the pillars marked the arena edges.
Recently the scientists from Berland have discovered the remains of the ancient circus arena. They found only three pillars, the others were destroyed by the time.
You are given the coordinates of these three pillars. Find out what is the smallest area that the arena could have.

Input
The input file consists of three lines, each of them contains a pair of numbers –– coordinates of the pillar. Any coordinate doesn’t exceed 1000 by absolute value, and is given with at most six digits after decimal point.
Output
Output the smallest possible area of the ancient arena. This number should be accurate to at least 6 digits after the decimal point. It’s guaranteed that the number of angles in the optimal polygon is not larger than 100.
Sample Input
0.000000 0.000000
1.000000 1.000000
0.000000 1.000000
Sample Output
1.00000000

题意:
在古代 Berland 竞技场的马戏团被塑造成一个规则 (等角) 多边形, 角色的大小和角度可能因马戏团而异。竞技场的每个角落都有一根特别的柱子, 柱子之间的绳子标记着竞技场的边缘。
最近, 来自 Berland 的科学家发现了古代马戏团竞技场的遗迹。他们发现只有三根柱子, 其他的被毁坏了
你得到了这三根柱子的坐标。请找出竞技场中最小的区域。

解题思路:
如果要求正多边形面积最小,明显正多边形的顶点都在给定三点构成的三角形外接圆上。已知的是三角形三点坐标,借此可以求出三角形三边长,结合海伦公式 可以求得三角形面积。根据余弦定理分别求出三角形三边作为弦所对的圆心角的三角函数值,使用反三角函数求出圆心角的度数,由于圆心角的度数皆为正多边形中心角度数的倍数,可以通过求圆心角度数的最大公约数求出正多边形的中心角度数 t,已知组成正多边形的三角形面积为R^2*sint/2,而这样的三角形有 2*π/t个,,于是正多边形面积为π*R^2*sint/t;

#include<stdio.h>
#include<math.h>
double Pi=acos(-1.0);        //π的值
double EPS=1E-2;            //控制精度
struct Point 
{
    double x,y;
}P[3];
double len[3],a[3];        //len为边长,a为圆心角角度。
double Get(int i,int j) 
{    //求两点之间距离
    return sqrt((P[i].x-P[j].x)*(P[i].x-P[j].x)+(P[i].y-P[j].y)*(P[i].y-P[j].y));
}
double gcd(double a,double b) 
{    
    if(fabs(b)<EPS)
        return a;
    if(fabs(a)<EPS)
        return b;
    return gcd(b,fmod(a,b));    //fmod(a,b), double类型的取模
}
int main() 
{
    double t=0.0,A,r;
    for(int i=0;i<3;++i)
        scanf("%lf%lf",&P[i].x,&P[i].y);
    for(int i=0;i<3;t+=len[i],++i)
        len[i]=Get(i,(i+1)%3);
    t/=2;
    A=sqrt(t*(t-len[0])*(t-len[1])*(t-len[2]));    //求三角形面积
    r=len[0]*len[1]*len[2]/(4*A);                //求三角形外接圆半径
    for(int i=0;i<2;++i)
        a[i]=acos(1-len[i]*len[i]/(2*r*r));        //求圆心角度数
    a[2]=2*Pi-a[0]-a[1];                        //为防止误差,最后一个圆心角根据三角形三边作为弦所对的三个圆心角之和为360°求出
    t=gcd(a[0],gcd(a[1],a[2]));                    //求圆心角的最大公约数
    printf("%.6lf\n",(Pi*r*r*sin(t))/t);            //求正多边形面积
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qecode/article/details/80296845