zoukankan      html  css  js  c++  java
  • poj1020

    dfs

    题意:给定一个大正方形的边长,和若干个小正方形的边长,问大的能否由小的拼成。

    分析:我们从上到下,从左到右地拼,也就是没列在任意时刻都是上面一段连续的空间被占用,用len[i]记录第i列被占用了几格。用cnt[i]记录边长为i的正方形有几个,枚举要拼的正方形的时候枚举i,这样可以保证当一个正方形匹配失败时,相同的正方形不会被反复尝试。每次选择一个正方形拼到最靠上端的空间中,如果任何正方形都没法拼,则说明那块空间永远无法被占用,所以应该回溯。

    View Code
    #include <iostream>
    #include
    <cstdio>
    #include
    <cstdlib>
    #include
    <cstring>
    using namespace std;

    #define maxl 11
    #define maxn 17

    int cnt[maxl];
    int side, n, area;
    int len[maxl * maxn];

    bool chk(int used)
    {
    if (used == n)
    return true;
    int minl = 110, p = -1;
    for (int i = 0; i < side; i++)
    if (minl > len[i])
    {
    minl
    = len[i];
    p
    = i;
    }
    for (int i = 0; i < maxl; i++)
    if (cnt[i] && len[p] + i <= side && p + i <= side)
    {
    bool ok = true;
    for (int j = p; j < p + i; j++)
    if (len[j] != len[p])
    {
    ok
    = false;
    break;
    }
    if (ok)
    {
    cnt[i]
    --;
    for (int j = p; j < p + i; j++)
    len[j]
    += i;
    if (chk(used + 1))
    return true;
    for (int j = p; j < p + i; j++)
    len[j]
    -= i;
    cnt[i]
    ++;
    }
    }
    return false;
    }

    int main()
    {
    //freopen("t.txt", "r", stdin);
    int t;
    scanf(
    "%d", &t);
    while (t--)
    {
    memset(len,
    0, sizeof(len));
    memset(cnt,
    0, sizeof(cnt));
    scanf(
    "%d%d", &side, &n);
    area
    = 0;
    for (int i = 0; i < n; i++)
    {
    int a;
    scanf(
    "%d", &a);
    cnt[a]
    ++;
    area
    += a * a;
    }
    if (area == side * side && chk(0))
    printf(
    "KHOOOOB!\n");
    else
    printf(
    "HUTUTU!\n");
    }
    return 0;
    }

  • 相关阅读:
    PHP的这些基础知识你应该熟知
    PHP版的猴子选大王算法
    Linux常用命令,面试常考
    PHP中常见的数字掐头去尾操作方法
    永久重定向301与临时重定向302区别
    WordPress子模板继承
    双系统引导设置
    OpenCv
    SpringBoot后端跨域问题
    存储式参数校验
  • 原文地址:https://www.cnblogs.com/rainydays/p/2112918.html
Copyright © 2011-2022 走看看