• 【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
    ", minarea);
        for(i = 0; i < outnum; i++)
        {
                fprintf(out, "%d %d
    ", outr[i].x, outr[i].y);
        }
    
        return 0;
    }
  • 相关阅读:
    ASP.NET生成静态页
    IE9下silverlight 里边MessageBox.Show 失效!
    Android与iOS:谁更适合HTML 5?
    编程修改IIS7的MIME类型的问题
    (译)理解“渐进增强(Progressive Enhancement)”
    C# 获取msi文件的ProductCode
    修改chrome浏览器useragent;在电脑上也能打开pad 或者 iphone 的专用网站
    开始的iOS编程之前的准备
    测试博客
    Google Maps Android API v2
  • 原文地址:https://www.cnblogs.com/dplearning/p/3727478.html
Copyright © 2020-2023  润新知