【USACO】packrec

这道题卡了很久,开始没读清楚题,没看到题目中给的6个组合是仅可能的组合,一直自己想有多少种组合方式。后来才发现,于是就想到写遍历。我想的是,这六种情况下,每个位置摆哪个矩形是不确定的,于是可以对方块的排列方法遍历,对每个方块是横放还是竖放遍历。写了一个9层的循环,效率很低,有非常多的重复。不过通过了。

#include <stdio.h>

#include <stdlib.h>

#include <math.h>



typedef struct

{

    int x;

    int y;

}RECTANGLE;



typedef struct

{

    RECTANGLE r[2];

}RECRotate;





int cmp(const void *a1, const void *a2)

{

    return ((RECTANGLE *)a1)->x - ((RECTANGLE *)a2)->x;

}



int max(int a, int b)

{

    return a > b ? a : b;

}

int min(int a, int b)

{

    return a < b ? a : b;

}



int assem(int c, RECTANGLE r1, RECTANGLE r2, RECTANGLE r3, RECTANGLE r4, RECTANGLE *out)

{

    switch(c)

    {

    case 1:

        out->x = r1.x + r2.x + r3.x + r4.x;

        out->y = max(r4.y, max(r3.y, max(r1.y, r2.y)));

        break;

    case 2:

        out->x = max(r4.y, r1.x + r2.x + r3.x);

        out->y = max(r3.y, max(r1.y, r2.y)) + r4.x;

        break;

    case 3:

        out->x = max(r1.x + r2.x + r3.x, r3.x + r4.y);

        out->y = max(r1.y + r4.x, max(r3.y, r2.y + r4.x));

        break;

    case 4: //basic 4 and basic 5 have the same area

        out->x = max(r2.x, r3.x) + r1.x +r4.x;

        out->y = max(r2.y + r3.y, max(r1.y, r4.y));

        break;

    case 5:

        if(r3.y >= r4.y)

        {

            out->x = max(r2.y + r3.x, max(r3.x + r4.x, r1.x + r2.y));

            out->y = max(r1.y + r3.y, r2.x + r4.y);

        }

        break;

    default:

        break;

    }

    return 0;

}



int isfirst(RECTANGLE *outr, int num, RECTANGLE tmp) //判断答案是否第一次出现 因为计算有冗余 可能有相同答案出现多次

{

    int i;

    for(i = 0; i < num; i++)

    {

        if(tmp.x == outr[i].x || tmp.y == outr[i].x)

        {

            return 0;

        }

    }

    return 1;

}

int main()

{

    FILE *in, *out;

    RECRotate recin[4]; //原始输入矩阵

    RECTANGLE outr[10];



    int i, j[5], k[4];

    in = fopen("packrec.in", "r");

    out = fopen("packrec.out", "w");



    for(i = 0; i < 4; i++)

    {

        fscanf(in, "%d %d", &recin[i].r[0].x, &recin[i].r[0].y);

        recin[i].r[1].x = recin[i].r[0].y;

        recin[i].r[1].y = recin[i].r[0].x;

    }



    RECTANGLE R1;

    RECTANGLE R2;

    RECTANGLE R3;

    RECTANGLE R4;

    RECTANGLE OUTTMP;

    int minarea = 9999999;

    int outnum = 0;

    for(j[1] = 0; j[1] < 4; j[1]++) //对每个位置采用第几个方块遍历

    {

        for(j[2] = 0; j[2] < 4; j[2]++)

        {

            if(j[2] == j[1]) continue;

            for(j[3] = 0; j[3] < 4; j[3]++)

            {

                if(j[3] == j[2] || j[3] == j[1]) continue;

                for(j[4] = 0; j[4] < 4; j[4]++)

                {

                    if(j[4] == j[3] || j[4] == j[2] || j[4] == j[1]) continue;

                    for(k[0] = 0; k[0] < 2; k[0]++)

                    {

                        for(k[1] = 0; k[1] < 2; k[1]++) //对每个方块采用横放竖放遍历

                        {

                            for(k[2] = 0; k[2] < 2; k[2]++)

                            {

                                for(k[3] = 0; k[3] < 2; k[3]++)

                                {

                                    R1 = recin[j[1]].r[k[0]];

                                    R2 = recin[j[2]].r[k[1]];

                                    R3 = recin[j[3]].r[k[2]];

                                    R4 = recin[j[4]].r[k[3]];

                                    for(i = 1; i < 6; i++)   //对6种情况遍历

                                    {

                                        assem(i, R1, R2, R3, R4, &OUTTMP);

                                        if(OUTTMP.x * OUTTMP.y < minarea)

                                        {

                                            minarea = OUTTMP.x * OUTTMP.y;

                                            outnum = 1;

                                            outr[outnum - 1] = OUTTMP;

                                        }

                                        else if(OUTTMP.x * OUTTMP.y == minarea && isfirst(outr, outnum, OUTTMP))

                                        {

                                            outnum++;

                                            outr[outnum - 1] = OUTTMP;

                                        }

                                    }

                                }

                            }

                        }

                    }

                }

            }

        }

    }

    for(i = 0; i < outnum; i++) //令短边长在前

    {

        if(outr[i].x > outr[i].y)

        {

            int tmp = outr[i].x;

            outr[i].x = outr[i].y;

            outr[i].y = tmp;

        }

    }

    qsort(outr, outnum, sizeof(outr[0]), cmp);  //按照短边长从小到大输出



    fprintf(out, "%d\n", minarea);

    for(i = 0; i < outnum; i++)

    {

            fprintf(out, "%d %d\n", outr[i].x, outr[i].y);

    }



    return 0;

}

 

你可能感兴趣的:(USACO)