大白书中的题感觉一般都比较难,能理解书上代码就已经很不错了

按照经验,一般数据较小的题目,都有可能是用状态压缩来解决的

题意:问一个面积为x×y的巧克力,能否切若干刀,将其切成n块面积为A1,A2,,,An块巧克力。(每次只能沿直线切一块巧克力)

设计状态:

f(r, c, S) = 1表示r行c列的巧克力可以切成面积集合为S的若干块巧克力

分解问题:

f(r, c, S) = 1当且仅当

  1. 横着切:存在1≤r0<r和S的子集S0,使得f(r0, c, S0) = f(r-r0,c, S-S0) = 1.   或者
  2. 竖着切:存在1≤C0<C和S的子集S0,使得f(r, C0, S0) = f(r,C-C0, S-S0) = 1.

状态的优化:

因为f(r, c, S) = f(c, r, S),所以我们去掉一个参数,并且假设r≤c

记f(r, S)表示min(r, sum[S]/r)行max(r, sum[S]/r)列的巧克力能否切成面积和为sum[S]的若干块

DP函数中那句 int& ans;的作用是什么作用不太懂,我开始时去掉以后WA掉了,Orz

这句留着以后再弄懂吧,=_=||

将ans声明为f[S][x]的引用,这样ans在赋值的时候f[S][x]也相应被改变

 //#define LOCAL
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std; const int maxn = ;
const int maxw = + ;
int a[maxn], sum[ << maxn], f[ << maxn][maxw], vis[ << maxn][maxw]; int bitcount(int S)
{
return S == ? : (S & ) + bitcount(S >> );
} int dp(int S, int x)
{
if(vis[S][x]) return f[S][x];
vis[S][x] = ;
int& ans = f[S][x];
if(bitcount(S) == )
return ans = ;
int y = sum[S] / x;
for(int S0 = (S-)&S; S0 != ; S0 = (S0-)&S)
{
int S1 = S - S0;
if(sum[S0] % x == && dp(S0, min(x, sum[S0]/x)) && dp(S1, min(x, sum[S1]/x)))
return ans = ;
if(sum[S0] % y == && dp(S0, min(y, sum[S0]/y)) && dp(S1, min(y, sum[S1]/y)))
return ans = ;
}
return ans = ;
} int main(void)
{
#ifdef LOCAL
freopen("4794in.txt", "r", stdin);
#endif int kase = , n;
while(scanf("%d", &n) == && n)
{
int x, y;
scanf("%d%d", &x, &y);
for(int i = ; i < n; ++i)
scanf("%d", &a[i]); memset(sum, , sizeof(sum));
for(int i = ; i < ( << n); ++i)
for(int j = ; j < n; ++j)
if(i & ( << j))
sum[i] += a[j]; memset(vis, , sizeof(vis));
int All = ( << n) - ;
int ans;
if(sum[All] != x*y)
ans = ;
else
ans = dp(All, min(x, y));
printf("Case %d: %s\n", ++kase, ans ? "Yes" : "No");
}
return ;
}

代码君

LA 4794 Sharing Chocolate的更多相关文章

  1. LA 4794 - Sharing Chocolate dp

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

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

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

  3. UVALive 4794 Sharing Chocolate

    Sharing Chocolate Chocolate in its many forms is enjoyed by millions of people around the world ever ...

  4. 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 ...

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

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

  6. UVALive 4794 Sharing Chocolate DP

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

  7. LA 4794 状态DP+子集枚举

    状态压缩DP,把切割出的面积做状态压缩,统计出某状态下面积和. 设f(x,y,S)为在状态为S下在矩形x,y是否存在可能划分出S包含的面积.若S0是S的子集,对矩形x,y横切中竖切,对竖切若f(x,k ...

  8. UVa 1009 Sharing Chocolate (数位dp)

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

  9. LA4794 Sharing Chocolate

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

随机推荐

  1. 理解Session的几种模式

    一.写在前面 我们在使用ASP.NET开发的过程中,有时会进行数据存储以实现请求前后的状态保持(HTTP是无状态保持的协议),而Session作为一种快速简单易于实现的方式被我们经常使用,当然如果出于 ...

  2. 数据库表 copy

    db1为原数据库,db2为要导出到的数据库,fromtable 是要导出的表名 1.方法一:登录导出到的数据库,执行create table fromtable select * from db1.f ...

  3. mysql修改数据库表权限

    ps:通常我用的是:1.“grant all on *.* to root@'%' identified by 'yourpassword';”——这个还可以顺带设置密码.2.“flush privi ...

  4. win8系统输入法设置

    Windows 8系统自带微软拼音简捷输入法,无论是在Windows的开始屏幕新界面中还是Windows传统桌面里,按Shift键或者直接点击屏幕上的"中/英"标识即可切换中英文输 ...

  5. sqlite3中的数据类型

    大多数的数据库引擎(到现在据我们所知的除了sqlite的每个sql数据库引擎)都使用静态的.刚性的类型,使用静态类型,数据的类型就由它的容器决定,这个容器是这个指被存放的特定列. Sqlite使用一个 ...

  6. POJ 2891 Strange Way to Express Integers (解一元线性方程组)

    求解一元线性同余方程组: x=ri(mod ai) i=1,2,...,k 解一元线性同余方程组的一般步骤:先求出前两个的解,即:x=r1(mod a1)     1x=r2(mod a2)     ...

  7. iOS第三方支付-支付宝支付

    处理手机中有无支付宝的情况支付宝调用接口: - (void)payOrder:(NSString *)orderStr      fromScheme:(NSString *)schemeStr    ...

  8. POJ 1961

    #include<iostream> #include<stdio.h> #define MAXN 1000001 using namespace std; char c[MA ...

  9. 几个经常用到的字符串的截取(java)

    几个经常用到的字符串的截取 string str="123abc456";int i=3;1 取字符串的前i个字符   str=str.Substring(0,i); // or  ...

  10. 540A: Combination Lock

    题目链接:http://codeforces.com/problemset/problem/540/A 题意: 输入的两个长度一样的数,求对应位置的某位数到下一个数需要最小的步长,每次只能先前或先后走 ...