題意:
給你一塊n*m面積的矩形,每次只切割只能橫着切或者是豎着切,問能不能切割成指定的面積的集合
分析:
如果使用沒有優化的DP,比較容易想到如下:
狀態:f[r][c][S],表示面積爲r*c的矩形能否切割成面積的集合S
狀態轉移: f[r][c][S] = 1, 當且緊當:f[r0][c][SR0] = f[r-r0][c][S^SR0] = 1 or f[r][c0][SC0] = f[r][c-c0][S-SC0] = 1
這樣狀態加上狀態轉移時間複雜度有點大
其實可以只枚舉需要的部分,因爲如果sum[S] != row*col的話,無論怎樣切割都不能到達目標,所以從枚舉S的子集開始,f[r][c][s] = f[c][r][s],
這裏因爲知道s和r就可以求出c了,狀態可以省略一維
Code:
#include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define DIR 4
#define DIM 2
#define STATUS 2
#define MAXROW 100 + 1
#define MAXN 45536 + 1
#define oo (~0u)>>1
#define INF 0x3F3F3F3F
#define REPI(i, s, e) for(int i = s; i <= e; i ++)
#define REPD(i, e, s) for(int i = e; i >= s; i --)
static const double EPS = 1e-5;
int n, row, col, final;
int f[MAXROW][MAXN], sum[MAXN], area[MAXROW];
inline int cnt_bit(int s)
{
int bit = 0;
REPI(i, 0, n-1) {
if( s&(1<<i) ) {
bit += 1;
}
}
return bit;
}
inline int dp(int r, int s)
{
if( -1 != f[r][s] ) {
return f[r][s];
}
if( 1 == cnt_bit(s) ) {
return f[r][s] = 1;
}
int c = sum[s]/r;
for(int s0 = (s-1)&s; s0; s0 = (s0-1)&s) {
int s1 = s^s0;
if( sum[s0]%r == 0 && dp(min(r, sum[s0]/r), s0) && dp(min(r, sum[s1]/r), s1) ) {
return f[r][s] = f[c][s] = 1;
}
if( sum[s0]%c == 0 && dp(min(c, sum[s0]/c), s0) && dp(min(c, sum[s1]/c), s1) ) {
return f[r][s] = f[c][s] = 1;
}
}
return f[r][s] = f[c][s] = 0;
}
int main(int argc, char const *argv[])
{
#ifndef ONLINE_JUDGE
freopen("test.in", "r", stdin);
#endif
int cas(1);
while( scanf("%d", &n) ) {
if( !n ) {
break;
}
scanf("%d %d", &row, &col);
REPI(i, 1, n) {
scanf("%d", &area[i]);
}
//cal sum
final = (1<<n)-1;
REPI(s, 0, final) {
sum[s] = 0;
REPI(j, 0, n-1) {
if( s&(1<<j) ) {
sum[s] += area[j+1];
}
}
}
REPI(i, 0, max(row, col)) {
memset(f[i], -1, sizeof(f[i]));
}
int flag = 0;
if( row*col != sum[final] ) {
flag = 0;
}
else {
flag = dp(min(row, col), final);
}
printf("Case %d: %s\n", cas ++, flag? "Yes" : "No");
}
return 0;
}