uva 12326 & hdu 4092 - Yummy Triangular Pizza(哈希+打表)

题目链接:uva 12326 &hdu
4092
Yummy Triangular Pizza

题目大意:给出n,表示用n个正三角形去组成图形,问可以组成多少种不同的三角形,旋转,镜像,都算同一种。

解题思路:参考别人的思路,很巧妙,主要就是建立三维坐标轴。


正立三角形x+y+z = 0

倒立三角形x+y+z ≠ 0

这样从初始装态为0 0 0的三角形开始逐个添加,每次进行旋转镜像,判断是否有没有重复。

每次判断重复的时候,枚举图形中的一个三角做为原点处理,生成hash值,以为n为多位16,所以x,y,z的范围不会大过8.

#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm>

using namespace std;
const int maxn = 16;

struct Trian {
    int x, y, z;
    Trian () {};
    Trian (int x, int y, int z) {
        this->x = x;
        this->y = y;
        this->z = z;
    }

    Trian add (int type) {
        int mv = (x+y+z == 0 ? 1 : -1);
        if (type == 0)
            return Trian(x, y+mv, z+mv);
        else if (type == 1)
            return Trian(x+mv, y, z+mv);
        else
            return Trian(x+mv, y+mv, z);
    }

    void rotate () {
        int tmp = x;
        x = y;
        y = z;
        z = tmp;
    }

    void overturn () {
        x = 1 - x;
        y = 1 - y;
        z = -z;
    }

    void move (int x, int y, int z) {
        this->x += x;
        this->y += y;
        this->z += z;
    }
};

bool operator == (const Trian& a, const Trian& b) {
    return a.x == b.x && a.y == b.y && a.z == b.z;
}

bool operator < (const Trian& a, const Trian& b) {
    if (a.x != b.x)
        return a.x < b.x;
    else if (a.y != b.y)
        return a.y < b.y;
    else
        return a.z < b.z;
}

struct Hash {
    int cnt, key[maxn+5];
};

bool operator < (const Hash& a, const Hash& b) {
    if (a.cnt != b.cnt)
        return a.cnt < b.cnt;
    for (int i = 0; i < a.cnt; i++)
        if (a.key[i] != b.key[i])
            return a.key[i] < b.key[i];
    return false;
}

struct Pizz {
    int cnt;
    Trian arr[maxn+5];
    Pizz () { cnt = 0; }

    bool add (const Trian& u) {

        for (int i = 0; i < cnt; i++)
            if (arr[i] == u)
                return false;
        arr[cnt++] = u;
        return true;
    }

    void remove () { cnt--; }

    Hash getKey () {
        Hash u;
        u.cnt = cnt;

        for (int i = 0; i < cnt; i++) {
            u.key[i] = arr[i].x + 8;
            u.key[i] <<= 4;
            u.key[i] += arr[i].y + 8;
            u.key[i] <<= 4;
            u.key[i] += arr[i].z + 8;
        }
        return u;
    }
};

set<Hash> vis;
int ans[maxn+5] = {0};

bool find (Pizz v) {
    for (int i = 0; i < 3; i++) {
        sort(v.arr, v.arr+v.cnt);
        if (vis.find(v.getKey()) != vis.end())
            return true;

        for (int j = 0; j < v.cnt; j++)
            v.arr[j].rotate();
    }
    return false;
}

bool search (Pizz u) {
    for (int i = 0; i < u.cnt; i++) {
        int x = u.arr[i].x;
        int y = u.arr[i].y;
        int z = u.arr[i].z;

        Pizz v = u;
        if (x + y + z == 0) {

            for (int j = 0; j < v.cnt; j++)
                v.arr[j].move(-x, -y, -z);

            if (find(v))
                return true;
        } else {

            for (int j = 0; j < v.cnt; j++) {
                v.arr[j].overturn();
                v.arr[j].move(x-1, y-1, z);
            }

            if (find(v))
                return true;
        }
    }
    return false;
}

void insert (Pizz u) {
    for (int i = 0; i < 3; i++) {
        sort(u.arr, u.arr+u.cnt);
        vis.insert(u.getKey());

        for (int j = 0; j < u.cnt; j++)
            u.arr[j].rotate();
    }
}

void dfs (Pizz u) {
    if (u.cnt == maxn+1)
        return;

    if (search(u))
        return;

    insert(u);
    ans[u.cnt]++;

    for (int i = 0; i < u.cnt; i++) {
        for (int j = 0; j < 3; j++) {
            Trian v = u.arr[i].add(j);
            if (u.add(v)) {
                dfs(u);
                u.remove();
            }
        }
    }
}
int rec[maxn+5] = {0, 1, 1, 1, 4, 6, 19, 43, 120, 307, 866, 2336, 6588, 18373, 52119, 147700, 422016};

int main () {
    /*
    Pizz u;
    u.add(Trian(0, 0, 0));
    dfs(u);

    for (int i = 0; i <= maxn; i++)
        printf("%d\n", ans[i]);
    */

    int cas, n;
    scanf("%d", &cas);
    for (int i = 1; i <= cas; i++) {
        scanf("%d", &n);
        printf("Case #%d: %d\n", i, rec[n]);
    }
    return 0;
}

uva 12326 & hdu 4092 - Yummy Triangular Pizza(哈希+打表)

时间: 2024-10-06 08:06:08

uva 12326 & hdu 4092 - Yummy Triangular Pizza(哈希+打表)的相关文章

hdu 2368 Alfredo&#39;s Pizza Restaurant(简单数学题)

转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2368 题目很简单,但是比较恶心,用sqrt WA到死也不过,不用秒过: 忍不住吐槽一下; Problem Description Traditionally after the Local Contest, judges and contestants go to their favourite restaurant,

UVa 674 &amp; hdu 2069 Coin Change (母函数,dp)

链接:uva 674 题意:有5中货币,价值分别为 50-cent, 25-cent, 10-cent, 5-cent,1-cent,数量都为无限个, 给定一个数 n,求用上述货币组成价值为 n 的方法有多少? 分析:因为n<=7489,可以用 母函数 或 dp 打表 对于dp状态方程为: dp[j]+=dp[j-c[i]] 母函数: #include<stdio.h> int c1[7500],c2[7500],w[5]={1,5,10,25,50};; void mhs() { in

HDU - 2368 Alfredo&#39;s Pizza Restaurant

题意:判断一个长方形是否能放到一个圆形里. 分析:将长方形的一条边贴近圆放置,求另一条边的最长长度lmax,若l<=lmax,则能放置. 注意:若这条边的长度大于直径,则一定不能放到圆里.因此,在求lmax的时候,在保证是非负数的情况下才能sqrt. #include<cstdio> #include<cstring> #include<cstdlib> #include<cctype> #include<cmath> #include&l

HDU 4588 Count The Carries 数位DP || 打表找规律

2013年南京邀请赛的铜牌题...做的很是伤心,另外有两个不太好想到的地方....a 可以等于零,另外a到b的累加和比较大,大约在2^70左右. 首先说一下解题思路. 首先统计出每一位的1的个数,然后统一进位. 设最低位为1,次低位为2,依次类推,ans[]表示这一位上有多少个1,那么有 sum += ans[i]/2,ans[i+1] += ans[i]/2; sum即为答案. 好了,现在问题转化成怎么求ans[]了. 打表查规律比较神奇,上图不说话. 打表的代码 #include <algo

HDU 1397 Goldbach&#39;s Conjecture(素数打表)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1397 Problem Description Goldbach's Conjecture: For any even number n greater than or equal to 4, there exists at least one pair of prime numbers p1 and p2 such that n = p1 + p2. This conjecture has not

HDU 1397 Goldbach&#39;s Conjecture【素数打表】

题意:给出n,问满足a+b=n且a,b都为素数的有多少对 将素数打表,再枚举 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include <cmath> 5 #include<stack> 6 #include<vector> 7 #include<map> 8 #include<algorithm> 9 #define mod=

UVa 10007 &amp; hdu 1131 Count the Trees (卡特兰数)

Count the Trees Time Limit:3000MS    Memory Limit:0KB     64bit IO Format:%lld & %llu SubmitStatus Description  Count the Trees  Another common social inability is known as ACM (Abnormally Compulsive Meditation). This psychological disorder is somewh

uva 12171 hdu 1771 Sculpture

//这题从十一点开始写了四十分钟 然后差错一小时+ 要吐了 这题题意是给很多矩形的左下角(x,y,z最小的那个角)和三边的长(不是x,y,z最大的那个角T-T),为组成图形的面积与表面积(包在内部的之算体积不算表面积) 解法:离散化+bfs,先把范围扩大(相当于在周围加上空气),然后bfs,遇到表面积直接加入,遇到非长方体的部分也直接加入,最后用总体积减去空气的体积,这样就可以把内部的体积计算进来而不计算其表面积.因为坐标范围比较大,要先离散化. //其实我对这题一直耿耿于怀,当年没进省队多少与

UVa 12167 &amp; HDU 2767 强连通分量 Proving Equivalences

题意:给出一个有向图,问最少添加几条有向边使得原图强连通. 解法:求出SCC后缩点,统计一下出度为0的点和入度为0的点,二者取最大值就是答案. 还有个特殊情况就是本身就是强连通的话,答案就是0. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <stack&