UVALive 4794 Sharing Chocolate
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
n
15), 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(1
x, y
100), 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的更多相关文章
- 【暑假】[深入动态规划]UVAlive 4794 Sharing Chocolate
UVAlive 4794 Sharing Chocolate 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=12055 ...
- UVALive 4794 Sharing Chocolate(状压,枚举子集)
n的规模可以状压,f[x][y][S]表示x行,y列,S集合的巧克力能否被切割. 预处理出每个状态S对应的面积和sum(S),对于一个合法的状态一定满足x*y=sum(S),实际上只有两个变量是独立的 ...
- UVALive 4794 Sharing Chocolate DP
这道题目的DP思想挺先进的,用状态DP来表示各个子巧克力块.原本是要 dp(S,x,y),S代表状态,x,y为边长,由于y可以用面积/x表示出来,就压缩到了只有两个变量,在转移过程也是很巧妙,枚举S的 ...
- LA 4794 Sharing Chocolate
大白书中的题感觉一般都比较难,能理解书上代码就已经很不错了 按照经验,一般数据较小的题目,都有可能是用状态压缩来解决的 题意:问一个面积为x×y的巧克力,能否切若干刀,将其切成n块面积为A1,A2,, ...
- LA 4794 - Sharing Chocolate dp
题意 有一块\(x*y\)的巧克力,问能否恰好分成n块,每块个数如下 输入格式 n x y a1 a2 a3 ... an 首先\(x \times y 必然要等于 \sum\limits_{i=1} ...
- 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 ...
- UVa 1009 Sharing Chocolate (数位dp)
题目链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_proble ...
- LA4794 Sharing Chocolate
传送门 记忆化搜索. 在下觉得sxy大佬的代码写得相当好,通篇的骚操作(因为我都不会呀),%%% 学到了 预处理每个状态的值.以前的我都是zz地枚举每一位.. for(int i=1;i<(1& ...
- 状压DP问题
状态压缩·一 题目传送:#1044 : 状态压缩·一 AC代码: #include <map> #include <set> #include <list> #in ...
随机推荐
- VS 2017产品秘钥
Enterprise: NJVYC-BMHX2-G77MM-4XJMR-6Q8QF Professional: KBJFW-NXHK6-W4WJM-CRMQB-G3CDH
- python面试题之什么是Tkinter ?
TKinter是一款很知名的Python库,用它我们可以制作图形用户界面.其支持不同的GUI工具和窗口构件,比如按钮.标签.文本框等等.这些工具和构件均有不同的属性,比如维度.颜色.字体等. > ...
- C#实体类get和set的作用
一,实体类属性访问存在两种写法: //第一种写法 private int _id; public int Id { set { _id = value; } get { return _id; } } ...
- docker 部署vsftpd服务、验证及java ftp操作工具类
docker部署vsftpd服务 新建ftp文件存储目录/home/ftp cd /home mkdir ftp 创建一个组,用于存放ftp用户 groupadd ftpgroups 创建ftp用户, ...
- IO,文件
IO 1. 定义 >在内存中存在数据交换的操作认为是IO操作,比如和终端交互 ,和磁盘交互,和网络交互等 2. 程序分类 >* IO密集型程序:在程序执行中有大量IO操作,而cpu运算较少 ...
- CWinThread 日志系统
CWinThread 日志系统 CWinThread 上继承写入日志 CStdioFile 继承文件
- C语言集成开发环境使用小记
时隔6年,我又重操C语言,是什么让我如此再下定决心?就是不想让自己所学过的知识就此荒废了,我重新以一个C语言初学者的身份(当然,稍稍有点基础,以前的知识忘得没这么快^_^)温故C语言,学习了几天,果真 ...
- cocos2D-X 屏幕适配
{ //https://v.youku.com/v_show/id_XNTIzOTM1MDYw.html }
- spring data jpa sql
CREATE TABLE cst_customer ( cust_id bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)', cust_name ...
- MDK(keil)4.7中文注释乱码解决
由于编码使用不统一导致别的开发环境下的文件在MDK(keil)下打开中文显示乱码,解决这一问题需要进行码制转换, 可以先将欲打开的文件转换成UTF-8格式(如在notepad中进行转换),也可以在打开 ...