zoukankan      html  css  js  c++  java
  • pku 1020

    题意:就是用几个小正方形,去拼成个大的正方形。

    思路:从大到小,从左到右,深搜,不是很难,

    网上的代码很简洁,我就不用自己的了,加点注释吧

    #include <stdio.h>
    #include <memory.h>
    int cnt[20]; //记录长度为i的正方形个数
    int len[50]; //记录目前第i列覆盖长度
    int cake_side, npiece;
    bool chk(int used)
    {
    if(used == npiece) //所有正方形都用上了,返回真,跳出
    return true;
    int min = 100, ind = -1;
    for(int i = 0; i < cake_side; i++) //枚举大蛋糕边的长度
    if(min > len[i])
    {
    min = len[i]; /* 找目前覆盖最小的那一列 */
    ind = i; //标记标号
    }
    //先放大的后放小的
    for(int i = 1; i <= 10; i++)
    if(cnt[i] && len[ind] + i <= cake_side) //有i这个边长,加上刚才最小的覆盖,合起来的值小于等于大正方形的边长
    {
    int wid = 0;/* 放置宽为 i 的 */
    for(int j = ind; j < cake_side; j++) //检测宽度是否符合要求,即是否放得下边长为i的正方形
    if(len[j] == len[ind]) wid++;
    else break;
    if(wid >= i) //能放下
    {
    cnt[i]--; //在下一层递归中,i用掉了一个
    for(int j = ind; j < ind + i; j++) //从ind到i+ind列覆盖的值更新,进入下一层递归
    len[j] += i;
    if(chk(used + 1)) //used表示用的正方形数
    return true;
    for(int j = ind; j < ind + i; j++) //更新值变回来,继续循环,不影响下次枚举
    len[j] -= i;
    cnt[i]++; //同上
    }
    }
    return false;
    }
    int main()
    {
    int cs = 0;
    scanf("%d", &cs);
    while(cs--)
    {
    memset(len, 0, sizeof(len));
    memset(cnt, 0, sizeof(cnt));
    int area = 0;
    scanf("%d %d", &cake_side, &npiece);
    for(int i = 0; i < npiece; i++)
    {
    int side;
    scanf("%d", &side);
    cnt[side]++;
    area += side * side;
    }
    if(cake_side * cake_side == area && chk(0))
    printf("KHOOOOB!\n");
    else
    printf("HUTUTU!\n");
    }
    return 0;
    }
  • 相关阅读:
    SpringMVC统一异常处理
    How to convert BigDecimal to Double in spring-data-mongodb framework
    DHCP动态主机配置协议
    你所听到的技术原理、技术本质到底是什么?
    前端技术及开发模式的演进,带你了解前端技术的前世今生
    金三银四,如何征服面试官,拿到Offer
    何谓多租户模式 ?
    骄傲的技术人,技术是你的全部吗?
    自我剖析,坚持有多难?
    从官方文档去学习之FreeMarker
  • 原文地址:https://www.cnblogs.com/FreeAquar/p/2155215.html
Copyright © 2011-2022 走看看