关闭

UVALive 4794 Sharing Chocolate

标签: dp
43人阅读 评论(0) 收藏 举报
分类:

题目链接:http://acm.hust.edu.cn/vjudge/problem/12055


题意:一块长x宽y的巧克力,每次只能横向或者竖向沿直线切割,问能否将一块巧克力切割成给定的n个面积。


思路:dp[x][s]表示还没有切出来的面积状态为s,剩余矩形的最短边为x时是否可行。

保证一开始就满足s的面积和等于初始矩形,所以切的过程中也是相等的,只需要记录一个边即可。

每次枚举s的子集,判断从两个方向切是否可行。记忆化搜索。


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <utility>
using namespace std;

#define rep(i,j,k) for (int i=j;i<=k;i++)
#define Rrep(i,j,k) for (int i=j;i>=k;i--)

#define Clean(x,y) memset(x,y,sizeof(x))
#define LL long long
#define ULL unsigned long long
#define inf 0x7fffffff
#define mod 100000007
const int maxn = 1<<15;
int n,uplim;
int X,Y;
int a[20];
int sum[maxn+10]; //∑s
bool vis[101][maxn+10];
bool dp[101][maxn+10];
int num[maxn+10];

void init()
{
    cin>>X>>Y;
    rep(i,1,n)
        scanf("%d",&a[i]);
    uplim = (1<<n)-1;
    rep(i,0,uplim)
    {
        num[i] = 0;
        sum[i] = 0;
        rep(j,0,n-1)
        if ( i & (1<<j) ) sum[i] += a[j+1],num[i]++;
    }
    Clean(vis,false);
}

bool dfs( int Lx , int state )
{
    if ( vis[Lx][state] ) return dp[Lx][state];
    if ( num[state] == 1 ) return true;
    vis[Lx][state] = true;
    int Ly = sum[state] / Lx;
    bool &ans = dp[Lx][state];
    ans = false;
    for ( int i = (state - 1) & state; i; i = (i - 1) & state )
    {
        if ( sum[i] % Lx == 0 && sum[state^i] % Lx == 0 )
            ans |= dfs( min( Lx , sum[i]/Lx ) , i ) & dfs( min( Lx , sum[state^i]/Lx ) , state^i );
        if ( sum[i] % Ly == 0 && sum[state^i] % Ly == 0 )
            ans |= dfs( min( Ly , sum[i]/Ly ) , i ) & dfs( min( Ly , sum[state^i]/Ly ) , state^i );
        if ( ans ) return true;
    }
    return ans;
}

bool solve()
{
    if ( sum[uplim] != X * Y || sum[uplim] % X ) return false;
    return dfs( min(X,Y) , uplim );
}

int main()
{
    int kase = 0;
    while( cin>>n )
    {
        if ( !n ) break;
        init();
        printf("Case %d: %s\n",++kase,solve()?"Yes":"No");
    }
    return 0;
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:31126次
    • 积分:2747
    • 等级:
    • 排名:第13151名
    • 原创:254篇
    • 转载:1篇
    • 译文:0篇
    • 评论:36条
    最新评论