UVALive 4794 Sharing Chocolate

原创 2016年08月29日 23:24:44

题目链接: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;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

LA 4794(Sharing Chocolate-记忆化搜索)

一个R*C的矩形,每次操作能通过一条线切割成两个长宽均为整数的矩形 是否能通过切割,得到面积恰为a1,a2,...,ana_1,a_2,...,a_n记忆化搜索1..n的子集 dpr,Sdp_{r...

dp 专题系列(二):LA3983 Robotruck,LA4794 Sharing Chocolate,LA4394 String Painter,LA4327 Parade,Uva 10817

这几天做的多校联合状态很不好,而且多校的题目数据也略坑爹(居然赛后知道有输出文件为空的数据。。。。)。。。    说说这几天做的dp题目吧。。。    dp感觉是越来越切不动了,各种状态不会想。。...
  • nuptxxp
  • nuptxxp
  • 2012年08月03日 23:10
  • 2745

uvalive4794(集合+状态压缩)

题意: 有一块x*y的巧克力,每次可以切一刀,问切若干刀后(不能两块同时切),可不可以切成n块,面积分别是a1,a2...an;的巧克力: 思路: 看到final的题就怂了; 最后还是...

UVA 1099 Sharing Chocolate

#include #include #include #include #include #include #include #include using namespace std;...

uva 1099 Sharing Chocolate

题意:给定一个面积的巧克力,能否分解成n个给定面积的巧克力。 思路:记忆话搜索,d[r][S]表示r行,面积为S(用集合表示),是否可行,注意每次搜索的时候保证可以整除,因为需要根据面积来算出列的大...

UVA 1099 Sharing Chocolate - 状压dp

题目描述题目大意:给出一块长为x,宽为y的矩形巧克力,每次操作可以沿着一条直线把一块巧克力切割成两块长宽均为整数的巧克力,一次只能切一块巧克力。 问:是否可以经过若干次操作得到n块面积分别为a1, ...

LA 4794 状态压缩dp

//LA 4794 状压dp //据说是当年2010年全球总决赛最简单的一道题目 #define _CRT_SECURE_NO_WARNINGS #pragma warning(disable:499...

HDU 4794 Arnold (Fib数模 n 的应用)——2013 Asia Changsha Regional Contest

传送门 ArnoldTime Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota...

HDU 4794 Arnold (斐波那契数模 n 的应用)

题意:对一个N*N的矩阵进行若干次转换,每一次转换是矩阵的每一个像素(x,y) 会转移到((x+y)%N,(x+2*y)%N), 经过若干次转换会变回原来的矩阵,问最少要转换多少次才会变回原来的矩阵。...

动态规划,记忆化搜索(分享巧克力,LA 4794)

能想到是那种枚举子集的动态规划,结果写着写着成了模拟了= =。 S是位向量,代表着巧克力的集合。 dp[S]是一个vector,里面装着巧克力集合S能拼出的长方形。模拟转移方程就是枚举S的子集...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:UVALive 4794 Sharing Chocolate
举报原因:
原因补充:

(最多只允许输入30个字)