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 ...
随机推荐
- CentOS7下Docker与.net Core 2.2
一.使用 yum 安装(CentOS 7下) Docker 要求 CentOS 系统的内核版本高于 3.10 ,查看本页面的前提条件来验证你的CentOS 版本是否支持 Docker . 通过 una ...
- 哪些文件在vue项目中很重要,哪些可以删掉
是时候告诉你重要文件是哪些了,这是一个陆游,所以 需要路由配置 index.js 路由配置文件是index.js注意这个文件最开始就在集成路由了 然后最开始集成路由的地方可以不写后缀名字,因此注意这个 ...
- Unity打包IOS踩坑记
1. Xcode不显示模拟器 之前一直用真机调试,就没注意模拟器.今天要上传版本要用到模拟器截图,发现竟然Xcode的运行选项竟然没有显示模拟器. 也是网上找了各种方法,修改各种设置,清了各种文件夹都 ...
- 如何去掉万恶的wps屏保
自从换了上个UI的电脑后,就莫名其妙的多了屏保,最开始以为屏蔽掉就好了,发现他依然不屈不挠的有,然后就百度了好多,也没找到...心累 今天终于开窍了,在角落里找打了.话不多说,上图 打开首页,找到应用 ...
- mysql创建用户账号出错
在数据库中输入“create user 'tom'@'%' identified by '123456';”时,出现“ERROR 1819 (HY000): Your password does no ...
- jQuery遍历之向下遍历
html <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <ti ...
- 浅谈maven自动化构建工具
转载https://blog.csdn.net/zxm1306192988/article/details/76209062 Maven是什么[what] 1.Maven 是 Apache 软件基金会 ...
- springbootboot 语句
-- ------------------------------ Table structure for `user`-- ----------------------------DROP TABL ...
- 【JVM】内存区域
程序运行时,有六个地方都可以保存数据: 1. 寄存器:这是最快的保存区域,因为它位于和其他所有保存方式不同的地方:处理器内部.然而,寄存器的数量十分有限,所以寄存器是根据需要由编译器分配.我们对此没有 ...
- OC学习篇之---Foundation框架中的NSDirctionary类以及NSMutableDirctionary类
昨天学习了Foundation框架中NSArray类和NSMutableArray类:http://blog.csdn.net/jiangwei0910410003/article/details/4 ...