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 ...
随机推荐
- u盘在电脑读不出来,但别的可以读
其实一般这种问题都是驱动程序问题导致的,解决方法很简单,不管是win7还是win10都适用: 插入u盘然后在设备管理里删掉设备重新插拔试试. 详细步骤是: 插上U盘 打开设备管理器 ...
- MySQL 同一字段匹配多个值
delete from api_log WHERE curl LIKE '%.css' or curl LIKE '%.js' or curl LIKE '%.JPG'; 删除字段curl以 js,c ...
- MySQL-mysql_config_editor安全登录工具
mysql_config_editor出现在mysql5.6.6以后的版本,可以给指定的连接和密码生成一个加密文件.mylogin.cnf,默认位于当前用户家目录下.通过该文件可以使用mysql.my ...
- SQL语句优化方式--进阶篇
MYSQL性能 最大数据量 抛开数据量和并发数,谈性能都是扯淡(扯的最疼的那种).Mysql没有限制单表最大记录数,它取决与操作系统对文件大小的限制 文件系统 单文件大小限制 FAT32(采用32位二 ...
- MySQL Workbench无法显示左侧的navigator,只显示Object info和Session
问题描述:Mac版MySQL Workbench出现异常强制退出后,再次进入后左侧的navigator消失,左侧整个导航条消失了,只显示Object info和Session. 问题根源:MySQL ...
- HDU 4366 Successor( DFS序+ 线段树 )
Successor Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total S ...
- IIS Express 不允许的父路径
IIS Express 启动一个asp的网站,出现一个错误 Active Server Pages 错误 'ASP 0131' 不允许的父路径 对于IIS可以在可视化的IIS Manager中配置: ...
- python基础类型(字典:dict)
字典的介绍: 字典(dict)Python中唯一的一个映射类型.他是以{}括起来的键值对组成,在dict中key是唯一的.在保存的时候,根据key来计算出一个内存地址,然后将key-value保存到这 ...
- 【异常】Caused by: java.lang.IllegalStateException: Method has too many Body parameters
出现此异常原因是引文使用feign客户端的时候,参数没有用注解修饰 1.1GET方式错误写法 @RequestMapping(value="/test", method=Reque ...
- Python3.5-20190518-廖老师-自我笔记-模块
在Python中,一个.py文件就称之为一个模块(Module) 可以作为module的文件类型有".py".".pyo".".pyc".& ...