博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
蓝桥杯省赛[新手向题解] 2019 第十届 C/C++ A组 第九题 DP
阅读量:6093 次
发布时间:2019-06-20

本文共 2016 字,大约阅读时间需要 6 分钟。

蓝桥杯省赛[新手向题解] 2019 第十届 C/C++ A组 第九题 [传送门:暂无]


Problem Description

  \(N\)袋糖果,每袋\(K\)颗糖,一共存在\(M\)种糖果。求最少选多少袋糖果可以吃到所有种类糖果。

Input

  第一行仨整数\(N\),\(M\)\(K\)

  接下来N行每行\(K\)整数,第\(i\)行表示第\(i\)袋糖有哪几种糖果
  (可能两袋内容相同,也可能一袋里有相同种类的糖果,这不重要)
  (数据范围挺小,大概\(N≤200,M\)\(k≤20\)

Output

  输出最小袋数

并不想按格式写:

赛时:

  还剩40分钟的分钟的时候摸到最后两题,感觉这题希望比较大,遂果断最后一题骗分再回来写这题。结果这题从12:35开始想算法到12:50写完……果然还是DP爽。

想网络流的时候先看数据范围是不是能直接莽

(其实是因为不抄板子写不出网络流)

  每种味道存在或不存在,一共\(2^{M}=2^{20}=1024^2\)种状态,直接状压DP

感觉还是直接上?比较好解释:

  比如\(M=6,K=3\),一共有\(2^6=64\)种状态,用二进制表示分别为:
    \(0=(000000)_2\) 表示所有糖果都没有
    \(1=(000001)_2\) 表示只有第1种糖果
    \(2=(000010)_2\) 表示只有第2种糖果
    \(3=(000011)_2\) 表示有第1种和第2种糖果
    ......
    \(63=(111111)_2\) 表示所有糖果都有
    \(dp[i][j]\)表示搜索到第\(i\)袋的时候,达到状态\(j\)最少需要多少袋,最终需要的答案是\(dp[N][2^{M}]\)
    比如当前搜索到第\(4\)袋的内容为\(1,3,4\),对应的状态为\((001101)_2=13\),对于前3袋处理过的任意状态,比如有第3种和第5种糖果的状态\((010100)_2=20\),如果把两者结合,就会转移到有第\(1,3,4,5\)种糖果的状态\((011101)_2=29\),这里的运算是按位或(|),也就是只要两者其中之一包含\(i\)种糖果,合并的状态中就包含第\(i\)种糖果。按这个例子来说就是\(dp[3][20]\)根据输入的001101转移到了\(dp[4][29]=dp[3][20]+1\)
    要注意,\(dp[4][29]\)可能不止由\(dp[3][20]\)转移过来,我们要保留所有转移方案中袋数最小的,所以应该是\(dp[4][29] = min(dp[4][29],dp[3][20]+1)\)
    同时,如果放弃第4袋糖果,就有\(dp[4][20]=dp[3][20]\),即没有产生影响。

  对于第\(i\)袋糖果\(a_{i_1},a_{i_2}......a_{i_K}\),它的状态为\(p[i]=2^{a_{i_1}-1}\ |\ 2^{a_{i_2}-1}\ |\ ......\ |\ 2^{a_{i_K}-1}\),这里涉及二进制的转换,第\(i\)种糖果在二进制的右边第\(i\)位,它的十进制为\(2^{i-1}\),然后把每个糖果贡献加起来就是这袋的总贡献。但是,一袋糖里可能会有相同的,所以用加法就会出错,不过按位或就不会,因为1和1作按位或,结果仍然是1,即重复的糖果不影响结果。

  状态转移方程:
\[dp[i+1][j|p[i]] = min(dp[i+1][j|p[i]],dp[i][j] + 1)\]
  初始状态:
    到达没有糖的状态不需要任何袋数,\(dp[i][0]=0\)
    第0袋的时候,到达任何状态的最小袋数都是无穷大,即\(dp[0][j] = INF\)
  (可以滚动数组)

Codes:

咕咕咕~(随便写点,仅供参考)const int MAXN = 1024*1024;int dp[MAXN];int N,M,K;int main(){    cin >> N >> M >> K;    int MAXM = pow(2,M);    memset(dp,0x3f3f,sizeof(dp));    dp[0] = 0;    while(N--)    {        int now(0);        for(int i=0; i
> a; a = pow(2,a-1); now = (now | a); } for(int j=0; j

转载于:https://www.cnblogs.com/MMMMMMing/p/10611950.html

你可能感兴趣的文章
c#与SQL中 double 与 float
查看>>
类样式操作
查看>>
Python&HDF5目录
查看>>
Vue -- 双向过滤器去除html标签
查看>>
H5禁止底部横向滚动条,使一个元素居中
查看>>
android 的安全问题
查看>>
skatebroads
查看>>
一些常用的命令和cheat sheet
查看>>
转----------数据库常见笔试面试题 - Hectorhua的专栏 - CSDN博客
查看>>
Android 界面设计 java.lang.NullPointerException 异常的解决方法
查看>>
解决ctrl+shift+F快捷键eclipse格式化与输入法简繁转换冲突问题
查看>>
kali在vbox上运行设置共享文件夹
查看>>
【观点】程序员的七大坏毛病
查看>>
一起谈.NET技术,Mono向Mac OS应用程序开发示好
查看>>
Spring学习(16)--- 基于Java类的配置Bean 之 基于泛型的自动装配(spring4新增)...
查看>>
实验八 sqlite数据库操作
查看>>
四种简单的排序算法(转)
查看>>
Quartz2D之着色器使用初步
查看>>
多线程条件
查看>>
Git [remote rejected] xxxx->xxxx <no such ref>修复了推送分支的错误
查看>>