2013 ACM/ICPC Asia Regional Changsha Online – C题 Color Representation Conversion (坑爹模拟题)

题意:给你三种颜色表示模式,RGB,HSV和HSL,实现任意模式之间两两转化。

1.最好别看题目中给的转化公式描述,我觉得叙述的一点也不清楚,看维基百科,把维基百科上的公式一句一句翻译过来就好

2.在公式换算的时候,全部转成小数形式。例如:RGB的取值范围0-255转化成0-1, 即r = R/255.0, g = G/255.0 b = B/255.0……

3.HSL->RGB和HSV->RGB需要四舍五入,而HSV和HSL之间的互相转化需要通过RGB: HSV<=>RGB<=>HSL,这里转RGB的时候不需要四舍五入。

4.对于自己转自己的情况,例如RGB->RGB,直接原样输出。

写的时候脑子不是很清楚,加上WA之后各种瞎改,代码略丑= =凑合着看吧……

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>

using namespace std;

const double eps = 1e-9;

struct node
{
    int val[3];
    bool second;
    double ang[3];
};

char tar[8];
char ori[8];
node A, ans;

int dcmp( double a )
{
    if ( fabs(a) < eps ) return 0;
    return a < 0 ? -1 : 1;
}

int Round( double a )
{
    return (int)(a + 0.5);
}

void init()
{
    scanf( "%s", ori );
    //printf("A: ");
    char tmp[20];
    for ( int i = 0; i < 3; ++i )
    {
        scanf( "%s", tmp );
        sscanf( tmp, "%d", &A.val[i] );
        //printf( "%d ", A.val[i] );
    }
    A.second = false;
    //puts("");
    return;
}

void RGBtoHSL()
{
    double r, g, b;
    if ( A.second )
    {
        r = A.ang[0];
        g = A.ang[1];
        b = A.ang[2];
    }
    else
    {
        r = A.val[0]/255.0;
        g = A.val[1]/255.0;
        b = A.val[2]/255.0;
    }

    double h, l, s;

    //printf( "rgb: %f %f %f
", r, g, b );
    double maxi = max( max(r, g), b );
    double mini = min( min(r, g), b );

    double delta = maxi - mini;
    if ( dcmp( maxi - mini ) == 0 )
    {
        h = 0.0;
    }
    else if ( dcmp( maxi - r ) == 0 )
    {
        if ( dcmp( g - b ) >= 0 )
        {
            h = 60.0*(g-b)/delta+0;
        }
        else
        {
            h = 60.0*(g-b)/delta+360;
        }
    }
    else if ( dcmp( maxi - g ) == 0 )
    {
        h = 60.0*(b-r)/delta+120;
    }
    else if ( dcmp( maxi - b ) == 0 )
    {
        h = 60.0*(r-g)/delta+240;
    }

    l = 0.5*(maxi+mini);
    //printf("l:%f
", l);

    if ( dcmp(l) == 0 || dcmp( delta ) == 0 )
    {
        s = 0.0;
    }
    else if ( dcmp(l) > 0 && dcmp( 0.5 - l ) >= 0 )
    {
        s = delta/(maxi+mini);
    }
    else
    {
        s = delta/(2.0-(maxi+mini));
    }

    //printf( "%s ", tar );
    //printf("%.0f %.0f%% %.0f%%
", h+eps, s*100+eps, l*100+eps );
    //printf("%d %d%% %d%%
", Round(h+eps), Round(s*100+eps), Round(l*100+eps) );
    ans.val[0] = Round(h);
    ans.val[1] = Round(s*100);
    ans.val[2] = Round(l*100);
    return;
}

void RGBtoHSV()
{
    double r, g, b;
    if ( A.second )
    {
        r = A.ang[0];
        g = A.ang[1];
        b = A.ang[2];
    }
    else
    {
        r = A.val[0]/255.0;
        g = A.val[1]/255.0;
        b = A.val[2]/255.0;
    }

    double h, v, s;

    double maxi = max( max(r, g), b );
    double mini = min( min(r, g), b );

    double delta = maxi - mini;
    if ( dcmp( delta ) == 0 )
    {
        h = 0;
    }
    else if ( dcmp( maxi - r ) == 0 )
    {
        if ( dcmp( g - b ) >= 0 )
        {
            h = 60.0*(g-b)/delta+0;
        }
        else
        {
            h = 60.0*(g-b)/delta+360;
        }
    }
    else if ( dcmp( maxi - g ) == 0 )
    {
        h = 60.0*(b-r)/delta+120;
    }
    else if ( dcmp( maxi - b ) == 0 )
    {
        h = 60.0*(r-g)/delta+240;
    }

    if ( dcmp( maxi ) == 0 )
    {
        s = 0;
    }
    else s = (double)(maxi-mini)/maxi;

    v = maxi;

    //printf( "%s ", tar );
    //printf("%f %f %f
", h+eps, s*100+eps, v*100+eps );
    //printf("%d %d%% %d%%
", Round(h+eps), Round(s*100+eps), Round(v*100+eps) );
    ans.val[0] = Round(h);
    ans.val[1] = Round(s*100);
    ans.val[2] = Round(v*100);

    return;
}

void jiuzheng( double &tC )
{
    if ( dcmp( tC ) < 0 ) tC += 1.0;
    if ( dcmp( tC - 1.0 ) > 0 ) tC -= 1.0;
    return;
}

double GetRGB( double p, double q, double tC )
{
    if ( dcmp( 1.0/6.0 - tC ) > 0 )
    {
        return p + ( (q - p) * 6.0 * tC );
    }
    else if ( dcmp( 0.5 - tC ) > 0 )
    {
        return q;
    }
    else if ( dcmp( 2.0/3.0 - tC ) > 0 )
    {
        return p + ( (q-p)*4.0 - (q-p)*6.0*tC );
    }
    else return p;
}

void HSLtoRGB()
{
    double h, s, l;
    double r, g, b;
    //int R, G, B;

    h = A.val[0]/360.0;
    s = A.val[1]/100.0;
    l = A.val[2]/100.0;

    if ( dcmp(s) == 0 )
    {
        r = l;
        g = l;
        b = l;
    }
    else
    {
        double p, q, tR, tG, tB;

        if ( dcmp( 0.5 - l ) > 0 )
            q = l * ( 1.0 + s );
        else q = l + s - ( l * s );

        p = 2 * l - q;

        tR = h + 1.0/3.0;
        tG = h;
        tB = h - 1.0/3.0;

        jiuzheng( tR );
        jiuzheng( tG );
        jiuzheng( tB );

        //r = GetRGB( p, q, tR )*255.0;
        r = GetRGB( p, q, tR );
        //g = GetRGB( p, q, tG )*255.0;
        g = GetRGB( p, q, tG );
        //b = GetRGB( p, q, tB )*255.0;
        b = GetRGB( p, q, tB );
    }

    //printf( "%s ", tar );
    //printf( "RGB: %d %d %d
", r, g, b );
    A.ang[0] = r;
    A.ang[1] = g;
    A.ang[2] = b;
    A.val[0] = Round( r * 255 );
    A.val[1] = Round( g * 255 );
    A.val[2] = Round( b * 255 );
    //printf("HSLtoRGB: %d %d %d
", A.val[0], A.val[1], A.val[2] );
    for ( int i = 0; i < 3; ++i )
        ans.val[i] = A.val[i];

    return;
}

void HSVtoRGB()
{
    double h, s, v;
    int R, G, B;
    double r, g, b;

    h = A.val[0];
    s = A.val[1] / 100.0;
    v = A.val[2] / 100.0;

    if ( dcmp(s) == 0 )
    {
        r = g = b = v;
    }
    else
    {
        int hi = (int)floor(h/60);
        double f = h / 60 - hi;
        double p = v * ( 1 - s );
        double q = v * ( 1 - f*s );
        double t = v * ( 1 - (1-f)*s );

        switch( hi )
        {
            case 0: r = v, g = t, b = p; break;
            case 1: r = q, g = v, b = p; break;
            case 2: r = p, g = v, b = t; break;
            case 3: r = p, g = q, b = v; break;
            case 4: r = t, g = p, b = v; break;
            case 5: r = v, g = p, b = q; break;
        }
    }

    R = Round( r * 255.0 );
    G = Round( g * 255.0 );
    B = Round( b * 255.0 );

    //printf( "%s ", tar );
    //printf( "%d %d %d
", R, G, B );
    A.ang[0] = r;
    A.ang[1] = g;
    A.ang[2] = b;

    A.val[0] = R;
    A.val[1] = G;
    A.val[2] = B;
    for ( int i = 0; i < 3; ++i )
        ans.val[i] = A.val[i];
    return;
}

void HSVtoHSL()
{
    HSVtoRGB();
    A.second = true;
    RGBtoHSL();
    return;
}

void HSLtoHSV()
{
    HSLtoRGB();
    A.second = true;
    RGBtoHSV();
    return;
}

int main()
{
    while ( scanf( "%s", tar ) == 1 )
    {
        init();
        if ( ori[0] == 'R' )
        {
            if ( tar[2] == 'L' ) RGBtoHSL();
            else if ( tar[0] == 'R' )
            {
                for ( int i = 0; i < 3; ++i )
                    ans.val[i] = A.val[i];
            }
            else RGBtoHSV();
        }
        else if ( ori[2] == 'L' )
        {
            if ( tar[0] == 'R' ) HSLtoRGB();
            else if ( tar[2] == 'L' )
            {
                for ( int i = 0; i < 3; ++i )
                    ans.val[i] = A.val[i];
            }
            else HSLtoHSV();
        }
        else
        {
            if ( tar[0] == 'R' ) HSVtoRGB();
            else if ( tar[2] == 'V' )
            {
                for ( int i = 0; i < 3; ++i )
                    ans.val[i] = A.val[i];
            }
            else HSVtoHSL();
        }

        printf( "%s ", tar );
        if ( tar[0] == 'R' )
        {
            printf( "%d %d %d
", ans.val[0], ans.val[1], ans.val[2] );
        }
        else printf( "%d %d%% %d%%
", ans.val[0], ans.val[1], ans.val[2] );
    }
    return 0;
}
原文地址:https://www.cnblogs.com/GBRgbr/p/3335707.html