题目链接:

点击打开链接

题目大意:

给出一个二阶矩阵A,求一个二阶矩阵B,且|B| = 0 ,使A-B的所有项的绝对值中的最大值最小

题目分析:

首先这道题很容易想到二分答案,那么如何判断当前情况下有没有解呢?

首先如果当前的最小值为x

那么假设矩阵A

a b

c d

那么矩阵B为

a1 b1

c1 d1

那么| a1 -a | <= d,其他的也类似,那么这是a1~d1的取值范围,那么就可求出a1*d1和c1*b1的取值范围,因为求出的范围是一个连续的区间,所以只要两个区间相交,那么当前d就有解,因为d有解,那么对于x>=d一定也有解,所以二分即可

对于浮点数的二分,可以直接给出二分的次数,次数越多,复杂度越高,同样的精度也越高,复杂度是times*log(1e9);

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
#define eps 1e-10

using namespace std;

int a,b,c,d;

double getMax ( double x , double y , double d )
{
    double temp = (x-d)*(y+d);
    temp = max ( (x-d)*(y-d) , temp );
    temp = max ( (x+d)*(y-d) , temp );
    temp = max ( (x+d)*(y+d) , temp );
    return temp;
}

double getMin ( double x , double y , double d )
{
    double temp = (x-d)*(y-d);
    temp = min ( (x-d)*(y+d) , temp );
    temp = min ( (x+d)*(y-d) , temp );
    temp = min ( (x+d)*(y+d) , temp );
    return temp;
}

bool check ( double x )
{
    double l1 = getMin ( a , d , x );
    double r1 = getMax ( a , d , x );
    double l2 = getMin ( b , c , x );
    double r2 = getMax ( b , c , x );
    if ( l1 <= r2 && r1 >= l2 ) return true;
    return false;
}

int main ( )
{
    while ( ~scanf ( "%d%d%d%d" , &a , &b , &c , &d ) )
    {
        double l , r , mid;
        r = max ( max ( abs(a),abs(b)) , max ( abs(c) , abs(d) ) ); 
        l = 0;
        int num = 1000000;
        while ( num-- )
        {
            mid = (l+r)/2.0;
            if ( check( mid ) ) r = mid;
            else l = mid;
        }
        printf ( "%.10lf\n" , l );
    }
}