最近经常做到组合计数的题目,每当看到这种题目第一反应总是组合数学,然后要用到排列组合公式,以及容斥原理之类的。。然后想啊想,最后还是不会做。。

但是比赛完之后一看,竟然是dp。。例如前几天的口号匹配求方案数的题目,今天的uva4656,以及hdu4248都是这种类型的题目。。

说说uva4565吧。

题意大概意思是:有N种纸牌,G给位置。。然后给定每种纸牌最少排几张,求满足的方案。

这样一来我们怎么划分状态呢?以位置?

不,我们得用纸牌来划分状态,并枚举纸牌之前用了几张

那么用f[i][j]表示前I个纸牌已经满足题意,且总共放了j个位置的方案数。那么 f[i][j] = sigma(f[i-1][k] * c[G - k][j - k]){j - k >= a[i]}

至于为什么是 f[i-1][k] * c[G - k][j - k],我们可以这样理解:

反正总的位置固定,选取的j-k个在剩下的G-k个里选择位置就行了。。(这样不会有问题吧)

hdu4248:

这一题自己懒得写了,转自这个博客http://www.cnblogs.com/sweetsc/archive/2012/07/17/2595189.html

我觉得写得很不错!

题意:有N种石头,每种石头有A1,A2....AN个,现取出一些石头组成序列,求可以组成多少种序列

例如:3种:可以产生:B; G; M; BG; BM; GM; GB; MB; MG; BGM; BMG; GBM; GMB; MBG; MGB.

我们采用动态规划的思想,划分阶段:按照石头种类划分阶段。于是乎,咱们对于第i种石头,相当于之前石头的颜色并不重要,借助高中数学插板法的思想,假如之前的i - 1 种石头,拼出了长      度为len,那么,相当于有len + 1个空,咱们要放第 i 种石头进去,于是乎,转化成了经典问题,我比较得意的总结:

球和球 盒和盒 空盒 情况数
有区别 有区别 有空盒 m^n
有区别 有区别 无空盒 M!s(n,m)
有区别 无区别 有空盒 S(n,1)+s(n,2)+…+s(n,m),n>=m
      S(n,1)+s(n,2)+…+s(n,n),n<=m
有区别 无区别 无空盒 S(n,m)
无区别 有区别 有空盒 C(n+m-1,n)
无区别 有区别 无空盒 C(n-1,m-1)
无区别 无区别 有空盒 DP
无区别 无区别 无空盒 DP

这里,第 i 种石头互相没有区别,len + 1个空有序,相当于有区别,可以有空盒,于是,如果咱们从第 i 种中放put个进去,情况数应该是 C(put + len , put)

于是设计状态:DP[i][j] 表示 用前 i 种石头,排出长度为 j 的可能数

然后,状态转移的时候,枚举在阶段 i 放入put个,DP[i + 1][j + put] += DP[i][j] * C(put + j, put) 即可

附上自己奇丑无比的代码:

Uva4656

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <set>
#include <stack>
#include <cmath>
#include <vector>
#include <algorithm>
#define MXN 50100
#define Inf 101010
#define M0(a) memset(a, 0, sizeof(a))
using namespace std;
double c[][], f[][];
int a[], sum[];
int n, m;
void init(){
M0(c);
for (int i = ; i <= ; ++i)
c[i][] = ;
for (int i = ; i <= ; ++i)
for (int j = ; j <= i; ++j)
c[i][j] = c[i-][j] + c[i-][j-];
} void solve(){
M0(sum);
M0(f);
scanf("%d%d", &n, &m);
for (int i = ; i <= m; ++i){
scanf("%d", &a[i]);
sum[i] = sum[i-] + a[i];
}
f[][] = ;
for (int i = ; i <= m; ++i)
for (int j = sum[i]; j <= n; ++j){
for (int k = a[i]; k <= j; ++k)
f[i][j] += f[i-][j-k] * c[n - j + k][k];
}
for (int i = ; i <= n; ++i)
f[m][n] /= m;
printf("%.6lf\n", f[m][n] * 100.00);
} int main(){
// freopen("a.in", "r", stdin);
// freopen("a.out","w", stdout);
int T, cas = ;
scanf("%d", &T);
init();
for (int i = ; i <= T; ++i){
printf("Case #%d: ", i);
solve();
} // fclose(stdin); fclose(stdout);
}

hdu4248

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <set>
#include <stack>
#include <cmath>
#include <vector>
#include <algorithm>
#define MXN 50100
#define Inf 101010
#define P 1000000007
#define M0(a) memset(a, 0, sizeof(a))
using namespace std;
int c[][];
long long f[][];
int n, a[], m, sum[]; void init(){
for (int i = ; i <= ; ++i)
c[i][] = ;
for (int i = ; i <= ; ++i)
for (int j = ; j <= && j <= i; ++j)
c[i][j] = (c[i-][j] + c[i-][j-]) % P;
} void solve(){
m = ;
M0(f);
M0(sum);
for (int i = ; i <= n; ++i){
scanf("%d", &a[i]);
m += a[i];
sum[i] = m;
}
f[][] = ;
long long ans = ;
for (int i = ; i <= n; ++i)
for (int j = ; j <= sum[i]; ++j){
for (int k = ; k <= a[i]; ++k){
if (k > j) break;
f[i][j] = (f[i][j] + f[i-][j-k] * c[j][k]) % P;
}
if (i == n && j) ans = (ans + f[i][j]) % P;
}
printf("%I64d\n", ans);
} int main(){
//freopen("a.in", "r", stdin);
// freopen("a.out","w", stdout);
int T, cas = ;
init();
while (scanf("%d", &n) != EOF){
printf("Case %d: ", ++cas);
solve();
} fclose(stdin); fclose(stdout);
}

方案dp。。的更多相关文章

  1. NOIP2006金明的预算方案[DP 有依赖的背包问题]

    题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行”.今 ...

  2. cf1140E 回文串+染色方案dp

    有点硬核的dp..要用到一个结论.. /* 把原串拆成奇偶串,再拆成极大连续的-1串:该串两端都是非-1数,中间都是-1,并且下标要么都是偶数,要么都是技术 然后对所有这些串进行dp,dp[i][0] ...

  3. BZOJ1079:[SCOI2008]着色方案(DP)

    Description 有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块. 所有油漆刚好足够涂满所有木块,即c1+c2+...+ck=n.相邻两个 ...

  4. luogu P1417 烹调方案 |dp

    题目背景 由于你的帮助,火星只遭受了最小的损失.但gw懒得重建家园了,就造了一艘飞船飞向遥远的earth星.不过飞船飞到一半,gw发现了一个很严重的问题:肚子饿了~ gw还是会做饭的,于是拿出了储藏的 ...

  5. PS8625替代方案CS5211|CS5211可以替代兼容PS8625方案|DP转LVDS芯片方案

    PS8625|Parade普瑞 PS8625|Parade普瑞 PS8625芯片|Parade普瑞 PS8625方案|Parade普瑞 PS8625芯片代理|DP转LVDS|PS8625替代方案CS5 ...

  6. CS5218替代AG6310方案设计|替代AG6310方案|DP转HDMI 4K30Hz转换方案

    AG6310是一款实现显示端DP口转HDMI数据转换器.AG6310是一款单芯片解决方案,通过DP端口连接器传输视频和音频流,其DP1.2支持可配置的1.2和4通道,分别为1.62Gbps.2.7Gb ...

  7. CapstoneCS5212替代IT6516方案|DP转VGA芯片|替代兼容IT6516

    台湾联阳IT6516是一种高性能的DP显示端口到VGA转换器方案芯片.IT6516结合DisplayPort接收器和三重DAC,通过转换功能支持DisplayPort输入和VGA输出.内置Displa ...

  8. bzoj 1079: [SCOI2008]着色方案 DP

    1079: [SCOI2008]着色方案 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 803  Solved: 512[Submit][Status ...

  9. BZOJ.2660.[BJOI2012]最多的方案(DP)

    题目链接 首先我们知道: 也很好理解.如果相邻两项出现在斐波那契表示法中,那它们显然可以合并. 所以我们能得到\(n\)的斐波那契表示,记\(pos[i]\)为\(n\)的斐波那契表示法中,第\(i\ ...

随机推荐

  1. C语言中内存分布及程序运行中(BSS段、数据段、代码段、堆栈)

      BSS段:(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英文Block Started by Symbol的简称.BSS段属于静态内存分配. 数据段 : ...

  2. XiaoKL学Python(C)__future__

    __future__ in Python 1. from __future__ import xxxx 这是为了在低版本的python中使用可能在某个高版本python中成为语言标准的特性,从而 在将 ...

  3. HDU 3407.Zjnu Stadium 加权并查集

    Zjnu Stadium Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  4. 担心后端代码泄露?用delphi做后端,模板扣出来,随时可以变化。

    担心后端代码泄露?用delphi做后端,模板扣出来,随时可以变化. 本项目不是intraweb, unigui等类似的拖拉项目,只是一个简单 的模板引擎,理论上可以结合任何后端. 要就下载源码,作者保 ...

  5. phpstudy报告80端口被占用

    将所有的80端口修改为81后重启,还是不行

  6. How to convert a PDF file to JPEGs using PHP

    Hey, Today I would like to show you how we can convert PDF to JPEG using imagick extension. Imagick ...

  7. JDK 之资源文件管理

    JDK 之资源文件管理 JDK 规范目录(https://www.cnblogs.com/binarylei/p/10200503.html) 一.文件资源 user.home 用户目录,如 Linu ...

  8. 编程学习笔记(第三篇)面向对象技术高级课程:绪论-软件开发方法的演化与最新趋势(3)软件开发的现状、UML扩展

    一.软件开发的现状 软件领域正在发生一个巨变,特别是近几年来,软件领域正在发生翻天覆地的变化. 这一变化主要以这个云 + 端大数据, 这些是随着目前最先进的一些技术的产生而产生的. 随着这些新的技术以 ...

  9. Python之路(第十四篇)os模块

    一.os模块 1.os.getcwd() 获取当前工作目录(当前工作目录默认都是当前文件所在的文件夹) import os print(os.getcwd()) 2.os.chdir(path) 改变 ...

  10. 通过flask中的Response返回json数据

    使用flask的过程中,发现有时需要生成一个Response并返回.网上查了查,看了看源码,找到了两种办法: from flask import Response, json Response(jso ...