• 砝码称重3


    参考

    https://blog.csdn.net/livelylittlefish/article/details/6555347

    假设有280g盐,有一架天平,有两个砝码,分别是4g和14g 。能否在3次内将280g食盐分为100g和180g两堆,请详细描述你的解决方法。

    这是另外一种砝码称重问题,类似,但是又不同。砝码称重 这个是给定无限数量砝码,只需计算能不能组成一个重量,不用知道如何组合。砝码称重1是给定砝码个数和重量,以及可以组合的重量,求出任意一种重量是如何组合的。砝码称重2 给定重量和拆分的砝码个数,求拆分后每个砝码的重量。这道题是给定重量和砝码,求如何拆分物体。看似相同,实际上每一个都不一样的。

    我们知道4和14可以有这几种组合 0 4 10 14 18,那么问题就是280g物品如何在3次内(说是3次内,基本上就是至少需要3次,我们就按照给定的最大条件来计算,因为如果2次可以,那么3次肯定也可以)用上面的几种砝码组合,拆出100和180.

    如果是3次,那么盐肯定是4堆。不过感觉上好像帮不上什么忙。上面参考的作者对问题做了数学分析,可以参考一下。

    求解的话就是穷举,分别用这几种砝码组合方式拆分盐,把每次拆分的结果再递归拆分,3次之后得到拆分的所有可能,然后计算有没有符合条件的方案。

    这里可以看出,第一次不管如何拆分都是偶数,因为砝码和盐堆都是偶数,怎么组合也没有奇数。

    那么第二次呢?可能会出现奇数,比如用14的组合称出14g盐,14g盐平分就是7g。如果出现了奇数,按照题目是拆分成100g和180g是整数,所以就没办法拆分了,因为砝码只有偶数,如果用砝码拆分奇数,得到的会有小数,有了小数,这两堆就没办法继续了,因为再往下,小数会更多,而其他的堆没有小数,所以只能这一堆组合。如果拆分其他堆呢,因为另一堆是偶数,只能平分,也没意义,最后导致与没拆分一样。

    如果第二次没有奇数,那么第三次出现奇数也只有平分,那么就不可能出现100g和180g。因为第二次比如得出盐堆a b c,a b c都是偶数,如果把a平分为a1 a2,并且是奇数,那么a1 a2没办法与b c组合,因为b c是偶数,没办法相加得出100g和180g两个偶数,所以只能a1和a2组合,那么就是要求第二次就可以得出100和180,也就是与第二步一样,与没拆分结果一样。

    因为砝码和盐堆都是偶数,拆分的也是偶数,出现奇数只能平分,如果一路平分下去,那就要求第一步就直接得出了结果。因为如果只有一个偶数变成奇数,那么只能这两个奇数组合,与没拆分这一步结果一样。如果两个偶数拆分成奇数,那么要么拆分的两堆相互组合,要么内部自己组合,不管怎么组合,都是与没进行这一步结果一样。

    所以拆分过程中不可能出现奇数,如果出现,就可以直接跳过了。可以帮我们减少一些计算。

    我们看一下上面作者的第一种方法

    #define Max_Num 5
    using namespace std;
    int total = 280;  //the total weight of the heap of salt
    int heap1 = 100, heap2 = 180;  //the target weight of the two samll heaps of salt
    int wst[] = { 0, 4, 10, 14, 18 };  //all cases of the weights combination
    /* the first division result */
    int x[Max_Num] = { 0 }, y[Max_Num] = { 0 };
    /* the second division result */
    int x1[Max_Num][Max_Num] = { {0} };
    int x2[Max_Num][Max_Num] = { {0} };
    int yy1[Max_Num][Max_Num] = { {0} };
    int y2[Max_Num][Max_Num] = { {0} };
    /* the third division result */
    int x11[Max_Num][Max_Num][Max_Num] = { {{0}} }, x12[Max_Num][Max_Num][Max_Num] = { {{0}} };
    int x21[Max_Num][Max_Num][Max_Num] = { {{0}} }, x22[Max_Num][Max_Num][Max_Num] = { {{0}} };
    int y11[Max_Num][Max_Num][Max_Num] = { {{0}} }, y12[Max_Num][Max_Num][Max_Num] = { {{0}} };
    int y21[Max_Num][Max_Num][Max_Num] = { {{0}} }, y22[Max_Num][Max_Num][Max_Num] = { {{0}} };
    /** the first division, according to z=x+y, x <= y */
    void weight1()
    {
        int z = total;
        int k = 0, w = 0;
        for (k = 0; k < Max_Num; k++)
        {
            w = wst[k];
            x[k] = z / 2 - w;  //divide z
            y[k] = z / 2 + w;
            if (x[k] % 2 != 0)  //no need to judge y[k]
                x[k] = y[k] = 0;
        }
    }
    void weight2()
    {
        int i = 0, k = 0, w = 0;
        for (i = 0; i < Max_Num; i++)
        {
            if (x[i] == 0)  //no need to judge y[i]
                continue;
            for (k = 0; k < Max_Num; k++)
            {
                w = wst[k];
                x1[i][k] = (x[i] - w) / 2;  //divide x
                x2[i][k] = (x[i] + w) / 2;
                if (x1[i][k] % 2 != 0)  //no need to judge x2[i][k]
                    x1[i][k] = x2[i][k] = 0;
                if (x[i] == y[i])  //to avoid repeatance
                    continue;
                yy1[i][k] = (y[i] - w) / 2;  //divide y
                y2[i][k] = (y[i] + w) / 2;
                if (yy1[i][k] % 2 != 0)  //no need to judge y2[i][k]
                    yy1[i][k] = y2[i][k] = 0;
            }
        }
    }
    void weight3()
    {
        int i = 0, j = 0, k = 0, w = 0;
        for (i = 0; i < Max_Num; i++)
        {
            if (x[i] == 0)  //no need to judge y[i]
                continue;
            for (j = 0; j < Max_Num; j++)
            {
                for (k = 0; k < Max_Num; k++)
                {
                    w = wst[k];
                    if (x1[i][j] != 0)  //divide x1[i][j]
                    {
                        x11[i][j][k] = (x1[i][j] - w) / 2;
                        x12[i][j][k] = (x1[i][j] + w) / 2;
                        if (x11[i][j][k] % 2 != 0)  //x11[i][j][k] and x12[i][j][k] must be even
                            x11[i][j][k] = x12[i][j][k] = 0;
                    }
                    if (x2[i][j] != 0 && x1[i][j] != x2[i][j])  //divide x2[i][j], and to avoid repeatance
                    {
                        x21[i][j][k] = (x2[i][j] - w) / 2;
                        x22[i][j][k] = (x2[i][j] + w) / 2;
                        if (x21[i][j][k] % 2 != 0)  //x21[i][j][k] and x22[i][j][k] must be even
                            x21[i][j][k] = x22[i][j][k] = 0;
                    }
                    if (yy1[i][j] != 0)  //divide yy1[i][j]
                    {
                        y11[i][j][k] = (yy1[i][j] - w) / 2;
                        y12[i][j][k] = (yy1[i][j] + w) / 2;
                        if (y11[i][j][k] % 2 != 0)  //y11[i][j][k] and y12[i][j][k] must be even
                            y11[i][j][k] = y12[i][j][k] = 0;
                    }
                    if (y2[i][j] != 0 && yy1[i][j] != y2[i][j])  //divide y2[i][j], and to avoid repeatance
                    {
                        y21[i][j][k] = (y2[i][j] - w) / 2;
                        y22[i][j][k] = (y2[i][j] + w / 2;
                        if (y21[i][j][k] % 2 != 0)  //y21[i][j][k] and y22[i][j][k] must be even
                            y21[i][j][k] = y22[i][j][k] = 0;
                    }
                }
            }
        }
    }
    void dump_correct_results()
    {
        int i = 0, j = 0, k = 0;
        for (i = 0; i < Max_Num; i++)
        {
            if (x[i] == 0)  //no need to judge y[i]
                continue;
            for (j = 0; j < Max_Num; j++)
            {
                if (x1[i][j] == 0)  //no need to judge x2[i][j]
                    continue;
                for (k = 0; k < Max_Num; k++)
                {
                    if (x11[i][j][k] != 0 && (x11[i][j][k] + x2[i][j] == heap1 || x12[i][j][k] + x2[i][j] == heap1))  //divide x1[i][j]
                    {
                        printf("%d = %d + %d
    ", total, x[i], y[i]);
                        printf("%d = %d + %d
    ", x[i], x1[i][j], x2[i][j]);
                        printf("%d = %d + %d
    
    ", x1[i][j], x11[i][j][k], x12[i][j][k]);
                    }
                }
                for (k = 0; k < Max_Num; k++)
                {
                    if (x21[i][j][k] != 0 && (x21[i][j][k] + x1[i][j] == heap1 || x22[i][j][k] + x1[i][j] == heap1))  //divide x2[i][j]
                    {
                        printf("%d = %d + %d
    ", total, x[i], y[i]);
                        printf("%d = %d + %d
    ", x[i], x1[i][j], x2[i][j]);
                        printf("%d = %d + %d
    
    ", x2[i][j], x21[i][j][k], x22[i][j][k]);
                    }
                }
            }
            for (j = 0; j < Max_Num; j++)
            {
                if (yy1[i][j] == 0)  //no need to judge y2[i][j]
                    continue;
                for (k = 0; k < Max_Num; k++)
                {
                    if (y11[i][j][k] != 0 && (y11[i][j][k] + y2[i][j] == heap1 || y12[i][j][k] + y2[i][j] == heap1))  //divide yy1[i][j]
                    {
                        printf("%d = %d + %d
    ", total, x[i], y[i]);
                        printf("%d = %d + %d
    ", y[i], yy1[i][j], y2[i][j]);
                        printf("%d = %d + %d
    
    ", yy1[i][j], y11[i][j][k], y12[i][j][k]);
                    }
                }
                for (k = 0; k < Max_Num; k++)
                {
                    if (y21[i][j][k] != 0 && (y21[i][j][k] + yy1[i][j] == heap1 || y22[i][j][k] + yy1[i][j] == heap1))  //divide y2[i][j]
                    {
                        printf("%d = %d + %d
    ", total, x[i], y[i]);
                        printf("%d = %d + %d
    ", y[i], yy1[i][j], y2[i][j]);
                        printf("%d = %d + %d
    
    ", y2[i][j], y21[i][j][k], y22[i][j][k]);
                    }
                }
            }
        }
    }
    
    struct MyStruct
    {
        int weight;//当前是多重的盐
        int fm;//通过哪种砝码得到的
        MyStruct()
        {
            weight = 0;
            fm = 0;
        }
    };
    //num 已经拆分了多少次
    void cf(int num, int* cfyan)
    {
        if (num == 3)
        {
            if (cfyan[0] + cfyan[1] == 100 || cfyan[2] + cfyan[3] == 180)
            {
                cout << cfyan[0] << "||" << cfyan[1] << "||" << cfyan[2] << "||" << cfyan[3];
            }
            else if (cfyan[0] + cfyan[2] == 100 || cfyan[1] + cfyan[3] == 180)
            {
                cout << cfyan[0] << "||" << cfyan[2] << "||" << cfyan[1] << "||" << cfyan[3];
            }
            else if (cfyan[0] + cfyan[3] == 100 || cfyan[1] + cfyan[2] == 180)
            {
                cout << cfyan[0] << "||" << cfyan[3] << "||" << cfyan[1] << "||" << cfyan[2];
            }
        }
    }
    int main()
    {
        int yan = 280;
        int fm[] = { 0, 4, 10, 14, 18 };
        int cfyan[] = { 0, 0, 0, 0 };
        {
            weight1();
            weight2();
            weight3();
            dump_correct_results();
        }
        char inchar;
        cin >> inchar;
    }

    原作者的代码有个问题,没有覆盖作者第一篇提到的,先用一个砝码称出对应的盐,然后再拆分,作者的逻辑都是平分再去掉对应的砝码重量。

    这是上面作者的第二种解法,用链表组成树

    #define Max_Num 5
    #define To_Be_Devided 2
    #define total 280  //the total weight of the heap of salt
    int wst[] = { 0, 4, 10, 14, 18 };  //all cases of the weights combination
    int heap1 = 100, heap2 = 180;  //the target weight of the two samll heaps of salt
    struct Division_Node
    {
        int parent_be_divided_;  //array to_be_divided_[] divided from its parent with this index
        int step_;  //the node step in the division process
        int heap_[Max_Num - 1];  //all divisions of its parent position for all weights
        int to_be_divided_[2];  //salt heap index to be divided in next step
        struct Division_Node *next_[2 * Max_Num];  //all pointers to all child divisions
        int child_;  //the numbe of children (not NULL in array next_)
    };
    //the root, for step 1, heap_[0] will be divided
    static struct Division_Node root = { 0, 0, {total}, {0}, {NULL}, 0 };
    /** the first division, according to z=x+y, x <= y */
    void weight1()
    {
        int div = 0, k = 0, w = 0;
        struct Division_Node *cur = &root;
        int child = 0;
        int step = 1;
        for (div = 0; div < To_Be_Devided - 1; div++)  //for step 1, only divide heap_[0]
        {
            int curpos = cur->to_be_divided_[div];
            int z = cur->heap_[curpos];  //the current heap to be divided
            for (k = 0; k < Max_Num; k++)
            {
                w = wst[k];
                int x = (z - w) / 2;  //divide z
                int y = (z + w) / 2;
                if (x % 2 != 0)  //no need to judge y[k]
                    continue;
                //new a node in step 1
                struct Division_Node *node1 = (struct Division_Node*)malloc(sizeof(struct Division_Node));
                memset(node1, 0, sizeof(struct Division_Node));
                node1->parent_be_divided_ = curpos;
                node1->step_ = step;
                node1->heap_[curpos] = x;
                node1->heap_[step] = y;
                node1->to_be_divided_[0] = curpos;
                node1->to_be_divided_[1] = step;
                cur->next_[child++] = node1;  //link root and node1
            }
        }
        cur->child_ = child;
    }
    /** the second division, according to x=x1+x2, y=y1+y2, x1<=x2, y1<=y2
      but, x and y are saved in node1->to_be_divided_[0] and node1->to_be_divided_[1].
      so, unify them to be as x.
     */
    void weight2()
    {
        int div = 0, i = 0, k = 0, w = 0;
        struct Division_Node *cur = &root;
        int step = 2;
        for (i = 0; i < cur->child_; i++)  //for each node1 in step1
        {
            struct Division_Node *node1 = cur->next_[i];  //step 2 will use all nodes created in step 1
            //to avoid repeatance
            int to_be_divided = To_Be_Devided;
            if (node1->heap_[node1->to_be_divided_[0]] == node1->heap_[node1->to_be_divided_[1]])
                to_be_divided--;
            int child = 0;
            for (div = 0; div < to_be_divided; div++)  //for step 2, will divide x=heap_[0], y=heap_[1] of node1
            {
                int curpos = node1->to_be_divided_[div];
                int x = node1->heap_[curpos];  //the current heap to be divided
                for (k = 0; k < Max_Num; k++)
                {
                    w = wst[k];
                    int x1 = (x - w) / 2;  //divide x or y, use x in order to be in a uniform
                    int x2 = (x + w) / 2;
                    if (x1 % 2 != 0)  //no need to judge x2
                        continue;
                    //new a node in step 2
                    struct Division_Node *node2 = (struct Division_Node*)malloc(sizeof(struct Division_Node));
                    memset(node2, 0, sizeof(struct Division_Node));
                    memcpy(node2->heap_, node1->heap_, (Max_Num - 1) * sizeof(int));  //copy from its parent
                    node2->parent_be_divided_ = curpos;
                    node2->step_ = step;
                    node2->heap_[curpos] = x1;
                    node2->heap_[step] = x2;
                    node2->to_be_divided_[0] = curpos;
                    node2->to_be_divided_[1] = step;
                    node1->next_[child++] = node2;  //link current node1 and node2
                }
            }
            node1->child_ = child;
        }
    }
    /** the third division, according to
      x1=x11+x12, y1=y11+y12, x11<=x12, y11<=y12
      x2=x21+x22, y2=y21+y22, x21<=x22, y21<=y22
      but, x1 or x2 or y1 or y2 is saved in heap_ of each node2 with index node2->to_be_divided_[0]
      and node2->to_be_divided_[1]. so, unify them to be as x1.
     */
    void weight3()
    {
        int div = 0, i = 0, j = 0, k = 0, w = 0;
        struct Division_Node *cur = &root;
        int step = 3;
        for (i = 0; i < cur->child_; i++)  //for each node1 in step1
        {
            struct Division_Node *node1 = cur->next_[i];
            for (j = 0; j < node1->child_; j++)  //for each node2 of node1 in step2
            {
                struct Division_Node *node2 = node1->next_[j];
                //to avoid repeatance
                int to_be_divided = To_Be_Devided;
                if (node2->heap_[node2->to_be_divided_[0]] == node2->heap_[node2->to_be_divided_[1]])
                    to_be_divided--;
                int child = 0;
                for (div = 0; div < to_be_divided; div++)  //for step 3, will divide x1=heap_[0], x2=heap_[2] of node2
                {
                    int curpos = node2->to_be_divided_[div];
                    int x1 = node2->heap_[curpos];  //the current heap to be divided, x1, or x2, or y1, or y2
                    for (k = 0; k < Max_Num; k++)
                    {
                        w = wst[k];
                        int x11 = (x1 - w) / 2;  //divide x or y, use x in order to be in a uniform
                        int x12 = (x1 + w) / 2;
                        if (x11 % 2 != 0)  //no need to judge x12
                            continue;
                        //new a node in step 3
                        struct Division_Node *node3 = (struct Division_Node*)malloc(sizeof(struct Division_Node));
                        memset(node3, 0, sizeof(struct Division_Node));
                        memcpy(node3->heap_, node2->heap_, (Max_Num - 1) * sizeof(int));  //copy from its parent
                        node3->parent_be_divided_ = curpos;
                        node3->step_ = step;
                        node3->heap_[curpos] = x11;
                        node3->heap_[step] = x12;
                        node3->to_be_divided_[0] = curpos;  //in fact, this array in step3 needed for dump
                        node3->to_be_divided_[1] = step;
                        node2->next_[child++] = node3;  //link current node2 and node3
                    }
                }
                node2->child_ = child;
            }
        }
    }
    void dump_correct_results(struct Division_Node* node)
    {
        int i = 0, j = 0, k = 0;
        struct Division_Node *cur = node;
        for (i = 0; i < cur->child_; i++)  //for each node1 in step1
        {
            struct Division_Node *node1 = cur->next_[i];
            for (j = 0; j < node1->child_; j++)  //for each node2 of node1 in step2
            {
                struct Division_Node *node2 = node1->next_[j];
                for (k = 0; k < node2->child_; k++)  //for each node3 of node2 in step 3
                {
                    struct Division_Node *node3 = node2->next_[k];
                    /** unify them into the following equations
                      z = x + y, x <= y
                      x = x1 + x2, x1 <= x2
                      x1 = x11 + x12, x11 <= x12
                     */
                    int x11 = node3->heap_[node3->to_be_divided_[0]];
                    int x12 = node3->heap_[node3->to_be_divided_[1]];
                    int x2index = 0;
                    if (node3->parent_be_divided_ == node2->to_be_divided_[0])
                        x2index = node2->to_be_divided_[1];
                    else
                        x2index = node2->to_be_divided_[0];
                    int x2 = node2->heap_[x2index];
                    if (x11 + x2 == heap1 || x12 + x2 == heap1)
                    {
                        printf("%d = %d + %d
    ", total, node1->heap_[node1->to_be_divided_[0]],
                            node1->heap_[node1->to_be_divided_[1]]);
                        printf("%d = %d + %d
    ", node1->heap_[node2->parent_be_divided_],
                            node2->heap_[node2->to_be_divided_[0]],
                            node2->heap_[node2->to_be_divided_[1]]);
                        printf("%d = %d + %d
    
    ", node2->heap_[node3->parent_be_divided_], x11, x12);
                    }
                }
            }
        }
    }
    void free_all_nodes(struct Division_Node* node)
    {
        int i = 0, j = 0, k = 0;
        struct Division_Node *cur = node;
        for (i = 0; i < cur->child_; i++)  //for each node1 in step1
        {
            struct Division_Node *node1 = cur->next_[i];
            for (j = 0; j < node1->child_; j++)  //for each node2 of node1 in step2
            {
                struct Division_Node *node2 = node1->next_[j];
                for (k = 0; k < node2->child_; k++)  //for each node3 of node2 in step 3
                {
                    struct Division_Node *node3 = node2->next_[k];
                    free(node3);
                }
                free(node2);
            }
            free(node1);
        }
    }
    int main(/* int argc, char** argv */)
    {
        weight1();
        weight2();
        weight3();
        dump_correct_results(&root);
        free_all_nodes(&root);
    
        char inchar;
        cin >> inchar;
    }

    我做了改进,增加了单独称出一些盐的条件,不足之处,就是有重复数据,没有判断。

    int fmweight[] = { 0, 4, 10, 14, 18 };
    struct MNODE
    {
        vector<int> mweight;//当前拆分的盐堆
        vector<MNODE*> mnext;//当前盐堆对应的拆分
    };
    void devsalt(MNODE* pnode)
    {
        if (pnode->mweight.size() == 4)
        {
            if (pnode->mweight[0] + pnode->mweight[1] == 100)
            {
                cout << pnode->mweight[0] << " " << pnode->mweight[1] << "||" << pnode->mweight[2] << " " << pnode->mweight[3] << endl;
            }
            else if (pnode->mweight[0] + pnode->mweight[2] == 100)
            {
                cout << pnode->mweight[0] << " " << pnode->mweight[2] << "||" << pnode->mweight[1] << " " << pnode->mweight[3] << endl;
            }
            else if (pnode->mweight[0] + pnode->mweight[3] == 100)
            {
                cout << pnode->mweight[0] << " " << pnode->mweight[3] << "||" << pnode->mweight[1] << " " << pnode->mweight[2] << endl;
            }
            else if (pnode->mweight[1] + pnode->mweight[2] == 100)
            {
                cout << pnode->mweight[1] << " " << pnode->mweight[2] << "||" << pnode->mweight[0] << " " << pnode->mweight[3] << endl;
            }
            else if (pnode->mweight[1] + pnode->mweight[3] == 100)
            {
                cout << pnode->mweight[1] << " " << pnode->mweight[3] << "||" << pnode->mweight[0] << " " << pnode->mweight[2] << endl;
            }
            else if (pnode->mweight[2] + pnode->mweight[3] == 100)
            {
                cout << pnode->mweight[2] << " " << pnode->mweight[3] << "||" << pnode->mweight[0] << " " << pnode->mweight[1] << endl;
            }
        }
        else
        {
            for (int i = 0; i < pnode->mweight.size(); i++)
            {
                for (int j = 0; j < 5; j++)
                {
                    {
                        int x = (pnode->mweight[i] - fmweight[j]) / 2;
                        int y = (pnode->mweight[i] + fmweight[j]) / 2;
                        if (x % 2 == 0)
                        {
                            MNODE* tnode = new MNODE;
                            for (int p = 0; p < pnode->mweight.size(); p++)
                            {
                                if (p != i)
                                {
                                    tnode->mweight.emplace_back(pnode->mweight[p]);
                                }
                            }
                            tnode->mweight.emplace_back(x);
                            tnode->mweight.emplace_back(y);
                            pnode->mnext.emplace_back(tnode);
                            devsalt(tnode);
                        }
                    }
                    if(fmweight[j] > 0)
                    {
                        int x = pnode->mweight[i] - fmweight[j];
                        int y = fmweight[j];
                        if (x > 0 && x % 2 == 0)
                        {
                            MNODE* tnode = new MNODE;
                            for (int p = 0; p < pnode->mweight.size(); p++)
                            {
                                if (p != i)
                                {
                                    tnode->mweight.emplace_back(pnode->mweight[p]);
                                }
                            }
                            tnode->mweight.emplace_back(x);
                            tnode->mweight.emplace_back(y);
                            pnode->mnext.emplace_back(tnode);
                            devsalt(tnode);
                        }
                    }
                }
            }
        }
    }
    int main()
    {
        MNODE* phead = new MNODE;
        phead->mweight.emplace_back(280);
        devsalt(phead);
        char inchar;
        cin >> inchar;
    }

    虽然增加了单独称出某些盐的方法,但是并没有增加结果,因为如果单独称出某些盐,这道题只能是利用已知的盐堆,这样的话,情况更多,这里就没有处理。别忘了释放内存。

  • 相关阅读:
    JavaScript 与 Java 是两种完全不同的语言,无论在概念还是设计上。
    JavaScript 是脚本语言
    java String去除两端的空格和空字符
    response.sendRedirect 的功能是地址重定向(页面跳转)
    Java中“|”和“||”用法的区别
    如何居中div?
    DIV居中的几种方法
    table 中的tr 行点击 变换颜色背景
    Html-浅谈如何正确给table加边框
    背景图以拉伸方式(不重复)填充背景
  • 原文地址:https://www.cnblogs.com/studywithallofyou/p/12120992.html
Copyright © 2020-2023  润新知