4794_alt.cpp


1
#include <cstdio>
2
#include <iostream>
3
#include <map>
4
#include <set>
5
#include <vector>
6
#include <cstdlib>
7
#include <cstring>
8
9
using namespace std;
10
11
const int MAX_WIDTH = 100;
12
const int MAX_HEIGHT = 100;
13
const int MAX_PIECES = 15;
14
15
int heightTable[1<<MAX_PIECES][MAX_WIDTH+1];
16
const int IMPOSSIBLE = -1;
17
const int UNKNOWN = 0;
18
19
int nrPieces = -1;
20
int pieceSetToSize[1<<MAX_PIECES];
21
22
map<int, set<int> > sizeToPieceSets;
23
24
int computeSizeOfSet(int set)
25
{
26
    int sum = 0;
27
    for (int i = 1; i <= set; i <<= 1)
28
    {
29
        if (set & i) sum += pieceSetToSize[i];
30
    }
31
    return sum;
32
}
33
34
void precomputeSizes()
35
{
36
    sizeToPieceSets.clear();
37
    
38
    for (int pieceSet = 1; pieceSet < (1 << nrPieces); pieceSet++)
39
    {
40
        int size = computeSizeOfSet(pieceSet);
41
        pieceSetToSize[pieceSet] = size;
42
        
43
        if (sizeToPieceSets.find(size) == sizeToPieceSets.end())
44
        {
45
            sizeToPieceSets.insert(make_pair(size, set<int>()));
46
        }
47
        
48
        sizeToPieceSets[size].insert(pieceSet);
49
    }
50
}
51
52
int countPieces(int pieceSet)
53
{
54
    int count = 0;
55
    while (pieceSet > 0)
56
    {
57
        if (pieceSet & 1) count++;
58
        pieceSet >>=1;
59
    }
60
    return count;
61
}
62
63
int computeHeight(int pieceSet, int width, int height, int recDepth)
64
{   
65
    int currentSize = pieceSetToSize[pieceSet];
66
67
    //already calculated this combination
68
    if (heightTable[pieceSet][width] != UNKNOWN) return heightTable[pieceSet][width];
69
    
70
    //base case, one piece
71
    if (countPieces(pieceSet) == 1)
72
    {
73
        if (width * height == currentSize)
74
        {
75
            heightTable[pieceSet][width] = height;
76
        }
77
        else
78
        {
79
            heightTable[pieceSet][width] = IMPOSSIBLE;
80
        }
81
        return heightTable[pieceSet][width];
82
    }
83
    
84
    //try to split up the set and place the sets into the bar
85
    
86
    for (int possiblePieceSet = 1; possiblePieceSet < pieceSet; possiblePieceSet++)
87
    {
88
        int complimentaryPieceSet = pieceSet ^ possiblePieceSet;
89
        
90
        int possibleSize = pieceSetToSize[possiblePieceSet];
91
        int complimentarySize = pieceSetToSize[complimentaryPieceSet];
92
        
93
        //is it a proper subset
94
        if ((pieceSet & possiblePieceSet) != possiblePieceSet) continue;
95
        
96
        //can they fit
97
        if (possibleSize + complimentarySize != currentSize) continue;
98
        
99
        //can they fit vertically stacked
100
        if (possibleSize % width == 0 && complimentarySize % width == 0)
101
        {
102
            int possibleHeight = computeHeight(possiblePieceSet, width, possibleSize / width, recDepth + 1);
103
            int complimentaryHeight = computeHeight(complimentaryPieceSet, width, complimentarySize / width, recDepth + 1);
104
            
105
            if (possibleHeight != IMPOSSIBLE && complimentaryHeight != IMPOSSIBLE && possibleHeight + complimentaryHeight == height)
106
            {
107
                return heightTable[pieceSet][width] = height;
108
            } 
109
        }
110
        
111
        //can they fit horizontally stacked
112
        if (possibleSize % height == 0 && complimentarySize % height == 0)
113
        {
114
            int possibleWidth = (possibleSize / height);
115
            int complimentaryWidth = (complimentarySize / height);
116
            int possibleHeight = computeHeight(possiblePieceSet, possibleWidth, height, recDepth + 1);
117
            int complimentaryHeight = computeHeight(complimentaryPieceSet, complimentaryWidth, height, recDepth + 1);
118
            int widthSum = possibleWidth + complimentaryWidth;
119
            
120
            if (possibleHeight != IMPOSSIBLE && complimentaryHeight != IMPOSSIBLE && 
121
                possibleHeight == height && complimentaryHeight == height && widthSum == width)
122
            {
123
                return heightTable[pieceSet][width] = height;
124
            }
125
        }
126
    }
127
    
128
    //no solution found
129
    return heightTable[pieceSet][width] = IMPOSSIBLE;
130
}
131
132
int main()
133
{
134
    int testcase = 0;
135
    while (++testcase)
136
    {
137
        cin >> nrPieces;
138
        if (nrPieces == 0) break;
139
        
140
        memset(heightTable, UNKNOWN, sizeof(heightTable));
141
        
142
        //read chocolate bar
143
        int width = -1;
144
        int height = -1;
145
        
146
        cin >> width >> height;
147
148
        //read every piece
149
        int sumOfSizes = 0;
150
        for (int i = 0; i < nrPieces; i++)
151
        {
152
            cin >> pieceSetToSize[1<<i];
153
            sumOfSizes += pieceSetToSize[1<<i];
154
        }
155
        precomputeSizes();
156
        
157
        bool result = sumOfSizes != width * height ? false : computeHeight((1<<nrPieces)-1, width, height, 0) == height;
158
        cout << "Case " << testcase << ": " << (result ? "Yes" : "No") << endl;
159
160
    }
161
    return 0;
162
}