Sharing Chocolate
Chocolate in its many forms is enjoyed by millions of people around the world every day. It is a truly universal candy available in virtually every country around the world.

You find that the only thing better than eating chocolate is to share it with friends. Unfortunately your friends are very picky and have different appetites: some would like more and others less of the chocolate that you offer them. You have found it increasingly difficult to determine whether their demands can be met. It is time to writte a program that solves the problem once and for all!

Your chocolate comes as a rectangular bar. The bar consists of same-sized rectangular pieces. To share the chocolate you may break one bar into two pieces along a division between rows or columns of the bar. You or the may then repeatedly break the resulting pieces in the same manner. Each of your friends insists on a getting a single rectangular portion of the chocolate that has a specified number of pieces. You are a little bit insistent as well: you will break up your bar only if all of it can be distributed to your friends, with none left over.

For exampla, Figure 9 shows one way that a chocolate bar consisting of 3 x 4 pieces can be split into 4 parts that contain 6, 3, 2, and 1 pieces respectively, by breanking it 3 times (This corresponds to the first sample input.)

Input

The input consists of multiple test cases each describing a chocolate bar to share. Each description starts with a line containing a single integer n(1n15), the number of parts in which the bar is supposed to be split. This is followed by a line containing two integers x and y(1xy100), the dimensions of the chocolate bar. The next line contains n positive integers, giving the number of pieces that are supposed to be in each of the n parts.

The input is terminated by a line containing the integer zero.

Output

For each test case, first display its case number. Then display whether it is possible to break the chocolate in the desired way: display ``Yes" if it is possible, and ``No" otherwise. Follow the format of the sample output.

Sample Input

4

3 4

6 3 2 1

2

2 3

1 5

0

Sample Output

Case 1: Yes

Case 2: No

因为 n 只有15嘛 。。 那么很容易想到一个状态就是 dp[a][b][st] .. 表示 a * b 这么大的一个矩阵

能否组成集合 st 里面的元素..这样.. bool型的 dp[a][b][st] = 1 表示可以 0 表示不可以。

状态就有 x*y* 2^n 个 ,, 转移要用 O(x + y ) .... 花费过大..

那么先处理一个sum[st] 表示 。这个st这个集合的巧克力的面积和。

那么转移的时候两个子集合的面积和已是确定的...

那么在切一刀的情况下:

sum[st0] %x == 0 才能竖切..

sum[st0] %y == 0 才能横切..

既然 sum[st0]满足上述条件 ....sum[st^st0]也必然满足...因为已有sum[st] %x == 0 && sum[st] % y == 0.

那么就可先降一维..用dp[a][st]表示 ....集合st是否可由宽为a的矩阵构成 .. 要转移的状态数也变为O(1)lor~

那里递归bitcount 也要学学~

初始条件就是 x * y == sum[(1<<n)- 1]...

然后进行一个记忆话搜索...

 超时:

#include <bits/stdc++.h>
using namespace std;
const int N = ;
const int M = (<<);
bool dp[N][N][M] , vis[N][N][M];
int sum[M] , n , x , y ,area[N]; bool DP( int x , int y , int st )
{
if( x > y )swap( x , y );
if( vis[x][y][st] ) return dp[x][y][st];
vis[x][y][st] = true;
for( int st0 = st ; st0 ; st0 = (st0-)&st ){
for( int i = ; i <= ( x - )/ ; ++i ) {
if( sum[st0] == i * y && sum[st^st0] == (x-i) * y && DP(i,y,st0) && DP(x-i,y,st^st0) ) return dp[x][y][st] = true;
if( sum[st^st0] == i * y && sum[st0] == (x-i) * y && DP(i,y,st^st0) && DP(x-i,y,st0) ) return dp[x][y][st] = true;
}
for( int j = ; j <= ( y - ) / ; ++j ){
if( sum[st0] == x * j && sum[st^st0] == x*(y-j) && DP(x,j,st0) && DP(x,y-j,st^st0)) return dp[x][y][st] = true;
if( sum[st^st0] == x * j && sum[st0] == x*(y-j)&& DP(x,j,st^st0) && DP(x,y-j,st0)) return dp[x][y][st] = true;
}
}
return dp[x][y][st] = false;
} void init()
{
memset( dp , false , sizeof dp );
memset( vis , false , sizeof vis );
memset( sum , ,sizeof sum );
} void run()
{
cin >> x >> y ;
init();
for( int i = ; i < n ; ++i ) {
cin >> area[i] ;
if( area[i] > x * y ) { cout << "No" << endl; return ;}
for( int a = ; a * a <= area[i] ; ++a ){
if( area[i] % a == ){ int b = area[i] / a; dp[a][b][(<<i)] = vis[a][b][(<<i)] = true ; }
}
}
for( int st = ; st < (<<n); ++st ){
for( int i = ; i < ; ++i ){
if( st & (<<i) ) sum[st] += area[i] ;
}
}
int ALL = ( << n ) - ;
if( sum[ALL] != x * y || !DP( x , y , ALL ) )cout << "No" << endl;
else cout << "Yes" <<endl ; }
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
int cas = ;
while( cin >> n && n ) { cout << "Case "<< cas++ <<": "; run(); }
}
正解:
#include <bits/stdc++.h>
using namespace std;
const int N = ;
const int M = (<<);
bool dp[N][M] , vis[N][M];
int sum[M] , n , x , y ,area[N];
int bitcnt( int st ){ return st == ? : bitcnt(st/) + (st&); }
bool DP( int x , int st )
{
if( vis[x][st] ) return dp[x][st];
vis[x][st] = true;
int y = sum[st] / x ;
if( bitcnt(st) == ) return dp[x][st] = true;
for( int st0 = st ; st0 ; st0 = (st0-)&st ){
if( sum[st0] % x == && DP( min( x , sum[st0]/x ),st0) && DP(min(x,sum[st^st0]/x),st^st0)) return dp[x][st] = true;
if( sum[st0] % y == && DP( min( y , sum[st0]/y ),st0) && DP(min(y,sum[st^st0]/y),st^st0)) return dp[x][st] = true;
}
return dp[x][st] = false;
} void init()
{
memset( dp , false , sizeof dp );
memset( vis , false , sizeof vis );
memset( sum , ,sizeof sum );
} void run()
{
cin >> x >> y ;
init();
for( int i = ; i < n ; ++i ) cin >> area[i] ;
for( int st = ; st < (<<n); ++st ){
for( int i = ; i < ; ++i ){
if( st & (<<i) ) sum[st] += area[i] ;
}
}
int ALL = ( << n ) - ;
if( sum[ALL] != x * y || !DP( x , ALL ) )cout << "No" << endl;
else cout << "Yes" <<endl ;
}
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
int cas = ;
while( cin >> n && n ) { cout << "Case "<< cas++ <<": "; run(); }
}

UVALive 4794 Sharing Chocolate的更多相关文章

  1. 【暑假】[深入动态规划]UVAlive 4794 Sharing Chocolate

    UVAlive 4794 Sharing Chocolate 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=12055 ...

  2. UVALive 4794 Sharing Chocolate(状压,枚举子集)

    n的规模可以状压,f[x][y][S]表示x行,y列,S集合的巧克力能否被切割. 预处理出每个状态S对应的面积和sum(S),对于一个合法的状态一定满足x*y=sum(S),实际上只有两个变量是独立的 ...

  3. UVALive 4794 Sharing Chocolate DP

    这道题目的DP思想挺先进的,用状态DP来表示各个子巧克力块.原本是要 dp(S,x,y),S代表状态,x,y为边长,由于y可以用面积/x表示出来,就压缩到了只有两个变量,在转移过程也是很巧妙,枚举S的 ...

  4. LA 4794 Sharing Chocolate

    大白书中的题感觉一般都比较难,能理解书上代码就已经很不错了 按照经验,一般数据较小的题目,都有可能是用状态压缩来解决的 题意:问一个面积为x×y的巧克力,能否切若干刀,将其切成n块面积为A1,A2,, ...

  5. LA 4794 - Sharing Chocolate dp

    题意 有一块\(x*y\)的巧克力,问能否恰好分成n块,每块个数如下 输入格式 n x y a1 a2 a3 ... an 首先\(x \times y 必然要等于 \sum\limits_{i=1} ...

  6. UVa Live 4794 - Sharing Chocolate 枚举子集substa = (s - 1) & substa,记忆化搜索 难度: 2

    题目 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...

  7. UVa 1009 Sharing Chocolate (数位dp)

    题目链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_proble ...

  8. LA4794 Sharing Chocolate

    传送门 记忆化搜索. 在下觉得sxy大佬的代码写得相当好,通篇的骚操作(因为我都不会呀),%%% 学到了 预处理每个状态的值.以前的我都是zz地枚举每一位.. for(int i=1;i<(1& ...

  9. 状压DP问题

    状态压缩·一 题目传送:#1044 : 状态压缩·一 AC代码: #include <map> #include <set> #include <list> #in ...

随机推荐

  1. spring cloud 使用Eureka作为服务注册中心

    什么是Eureka?  Eureka是在AWS上定位服务的REST服务. Eureka简单示例,仅作为学习参考 在pom文件引入相关的starter(起步依赖) /*定义使用的spring cloud ...

  2. 46-python基础-python3-字符串-常用字符串方法(四)-join()-split()

    5-字符串方法 join()和 split() 1-join()方法 将字符串列表连接成一个单独的字符串. join()方法在一个字符串上调用,参数是一个字符串列表,返回一个字符串. 请注意,调用 j ...

  3. 八、hibernate的查询(HQL)

    HQL:Hibernate Query Language 提供更加丰富灵活.更为强大的查询能力 HQL更接近SQL语句查询语法 面向对象的查询 "from Children where ci ...

  4. 【学习总结】Python-3- 类型判断之 isinstance 和 type 的区别

    菜鸟教程-Python3-基本数据类型 关于类型查询: type() 函数:可以用来查询变量所指的对象类型 用 isinstance()函数:判断是否是某个类型 两者的区别: type()不会认为子类 ...

  5. Javascript基础五(BOM和DOM)

    1.BOM概念 什么是BOM?         BOM是Browser Object Model的缩写,简称浏览器对象模型.这个对象就是window         BOM提供了独立于内容而与浏览器窗 ...

  6. 2019-8-31-C#-使用汇编

    title author date CreateTime categories C# 使用汇编 lindexi 2019-08-31 16:55:58 +0800 2019-2-16 8:56:5 + ...

  7. JDBC、ibatis(mybatis)、Hibernate有什么不同?

    ①JDBC编程流程固定,同时将sql语句和java代码混在了一起,经常需要拼凑sql语句,细节很繁琐: ②ibatis(mybatis)它不完全是一个ORM框架,因为MyBatis需要程序员自己编写S ...

  8. spring 获取url参数

    1. usl格式: http://localhost:8080/contact/delete/3 java代码 @RequestMapping(value="/delete/{id}&quo ...

  9. 12.Unsafe原子性操作

    import sun.misc.Unsafe; /** * JDK8 * JDK 的此jar 包中的 Unsafe 类提供了硬件级别的原子性操作 */ public class UnsafeTest ...

  10. Ubuntu修改用户和root密码

    如果要修改root的密码:sudo passwd 如果要修改_当前_用户的密码:passwd 如果要修改其他用户的密码(你得有权限):sudo passwd USERNAME,USERNAME就是你要 ...