poj2436,poj3659,poj2430
这两题都体现了dp的核心:状态
dp做多就发现,状态一设计出来,后面的什么都迎刃而解了(当然需要优化的还要动动脑筋);
先说比较简单的;
poj2436 由题得知病毒种数<=15很小,于是我们就容易想到将病每个牛携带的病毒抽象成15位的二进制数
0表示这种病毒不存在,1表示病毒存在,于是设cowi携带的病毒转化为二进制数为a,cowj为b
则如果挤cowi和cowj,那么所含病毒数为a or b,由此dp就显然了;
var dp:array[..,..] of longint; //表示所含病毒数为j的情况下最多可以挤多少只牛
w,f:array[..] of longint;
s,ans,x,i,j,n,m,k,t,y,k1,k2:longint; function prework(x:longint):longint; //预处理数字代表的病毒种类数目
var t:longint;
begin
t:=;
while x<> do
begin
t:=t+x mod ;
x:=x div ;
end;
exit(t);
end; begin
readln(t,m,k);
s:= shl m-;
f[]:=;
for i:= to s do
begin
f[i]:=prework(i);
dp[,i]:=-;
end;
for i:= to t do
begin
read(x);
if x>k then readln
else begin
n:=n+;
w[n]:=;
for j:= to x do //转化为二进制
begin
read(y);
w[n]:=w[n]+ shl (y-);
end;
end;
end;
dp[,]:=;
k1:=;
k2:=;
ans:=;
for i:= to n do //dp
begin
k1:=k1 xor ; //滚动数组
k2:=k2 xor ;
dp[k2]:=dp[k1];
for j:= to s do
begin
x:=j or w[i]; //位运算
if (f[x]<=k) and (f[j]<=k) and (dp[k1,j]>=) then
dp[k2,x]:=max(dp[k2,x],dp[k1,j]+);
ans:=max(dp[k2,x],ans);
end;
end;
writeln(ans);
end.
poj2436
写的比较随意,有些地方还可以优化 O(n*2^m)是可以在1s出来的,实际813ms(悬)
poj3659是树的最小支配集
这题贪心也是正确方法,但这里我介绍的是treedp
对于当前节点i,容易想的两种状态f[i,1]表示在i节点建立发射塔(属于支配集)
所以它的孩子节点状态就随意了,每个子节点选个最小的状态就行了;
f[i,0]表示在i节点不建立发射塔,但i和其子树都被覆盖了
所以f[i,0]=signma(min(f[j,0],f[j,1]))-min(f[k,0]-f[k,1]); j表示i的所有孩子,而k表示其中有一个孩子一定要属于支配集
注意不要漏了一种情况:那就是i可以不被儿子覆盖而被它的父亲覆盖,并且它的子树都是全覆盖的
f[i,2]=signma(min(f[j,0],f[j,1]))
最后的ans=min(f[root,0],f[root,1]);
实现起来还是很容易的,dfs到叶子然后想上更新
值得注意的是,题目给出的相邻结点而非父子关系,所以用图的形式存然后以任意一点做treedp即可
poj2430是使用k个矩形覆盖所用奶牛的最小覆盖面积
同样要设计好状态
设f[i,j,k]表示到覆盖到第i只奶牛使用j个木板,k表示覆盖结尾的状态,显然有4种
1.上下都圈而且上下是属于同一次圈的
2.上下都圈而且上下是不属于同一次圈的,属于两次圈的
3.只圈上面的
4.只圈下面的
然后就轻松了
code:复杂度O(nk+nlog2n)
const max=;
var f:array[..,..,..] of longint;
a,b:array[..] of longint;
i,j,k1,k2,n,k,m,w,ans,t:longint;
function findmin(t:longint):longint;
var p,k:longint;
begin
p:=max;
for k:= to do
p:=min(p,f[k1,j-t,k]);
exit(p);
end;
procedure sort(l,r: longint); //按列排序,上下都有牛时1在前2在后,这样处理dp的时候方便多
var i,j,x,y: longint;
begin
i:=l;
j:=r;
x:=a[(l+r) div ];
y:=b[(l+r) div ];
repeat
while (a[i]<x) or (a[i]=x) and (b[i]<y) do inc(i);
while (x<a[j]) or (a[j]=x) and (b[j]>y) do dec(j);
if not(i>j) then
begin
swap(a[i],a[j]);
swap(b[i],b[j]);
inc(i);
j:=j-;
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end; procedure doit1;
begin
f[k2,j,]:=min(f[k2,j,],f[k1,j,]+*(a[i]-a[i-]));
f[k2,j,]:=min(findmin()+,f[k2,j,]);
end; procedure doit2;
var p:longint;
begin
f[k2,j,]:=min(f[k1,j,]+*(a[i]-a[i-]),f[k2,j,]);
p:=min(min(f[k1,j-,],f[k1,j-,]),f[k1,j-,]);
f[k2,j,]:=min(f[k2,j,],p+a[i]-a[i-]+);
if j->= then
f[k2,j,]:=min(f[k2,j,],findmin()+);
end; procedure doit(x:longint);
var p:longint;
begin
p:=min(f[k1,j,x],f[k1,j,]);
f[k2,j,x]:=min(f[k2,j,x],p+a[i]-a[i-]);
f[k2,j,x]:=min(f[k2,j,x],findmin()+);
end; begin
readln(n,k,m);
for i:= to n do
readln(b[i],a[i]);
sort(,n);
for i:= to k do //初始化
for j:= to do
begin
f[,i,j]:=max;
f[,i,j]:=max;
end;
i:=;
f[,,]:=;
if a[i]=a[i+] then
begin
i:=;
f[,,]:=;
end
else begin
i:=;
if b[]= then f[,,]:=
else f[,,]:=;
end;
k1:=;
k2:=;
while i<=n do
begin
k1:=k1 xor ; //滚动数组
k2:=k2 xor ;
if a[i]=a[i+] then w:= else w:=;
for j:= to k do
begin
for t:= to do
f[k2,j,t]:=max;
doit1; //做4个状态,方程式自己动手比划一下就明白了
doit2;
if w= then
begin
if b[i]= then
doit()
else doit();
end;
end;
i:=i+w;
end;
ans:=max;
for i:= to do
ans:=min(ans,f[k2,k,i]);
writeln(ans);
end.
上述三道题都是非常好的设计状态题,状态是用dp解决问题的关键
特别poj2430一设计出状态,dp立马迎刃而解
poj2436,poj3659,poj2430的更多相关文章
- 10.22~10.28一周经典题目整理(meeting,BZOJ4377,POJ3659)
meeting:给正n边形每个点染上黑色或者白色,问有多少个同色的等腰三角形. 以正五边形为例这里将最上面的点作为顶点,得到若干对相等的腰 ,注意到以最上面的点作为顶点的等腰三角形的个数,等于颜色相等 ...
- 逆天通用水印支持Winform,WPF,Web,WP,Win10。支持位置选择(9个位置 ==》[X])
常用技能:http://www.cnblogs.com/dunitian/p/4822808.html#skill 逆天博客:http://dnt.dkil.net 逆天通用水印扩展篇~新增剪贴板系列 ...
- MySQL主从环境下存储过程,函数,触发器,事件的复制情况
下面,主要是验证在MySQL主从复制环境下,存储过程,函数,触发器,事件的复制情况,这些确实会让人混淆. 首先,创建一张测试表 mysql),age int); Query OK, rows affe ...
- Oracle安装部署,版本升级,应用补丁快速参考
一.Oracle安装部署 1.1 单机环境 1.2 Oracle RAC环境 1.3 Oracle DataGuard环境 1.4 主机双机 1.5 客户端部署 二.Oracle版本升级 2.1 单机 ...
- Syscall,API,ABI
系统调用(Syscall):Linux2.6之前是使用int0x80(中断)来实现系统调用的,在2.6之后的内核是使用sysentry/sysexit(32位机器)指令来实现的系统调用,这两条指令是C ...
- 【夯实PHP基础】PHP数组,字符串,对象等基础面面观
本文地址 分享提纲 1.数组篇 2.字符创篇 3.函数篇 4.面向对象篇 5.其他篇 /*************************** 一.数组篇 Begin***************** ...
- MSSQL 事务,视图,索引,存储过程,触发器
事务 事务是一种机制.是一种操作序列,它包含了一组数据库操作命令,这组命令要么全部执行,要么全部不执行. 在数据库系统上执行并发操作时事务是作为最小的控制单元来使用的.这特别适用于多用户同时操作的数据 ...
- 谁偷了我的热更新?Mono,JIT,iOS
前言 由于匹夫本人是做游戏开发工作的,所以平时也会加一些玩家的群.而一些困扰玩家的问题,同样也困扰着我们这些手机游戏开发者.这不最近匹夫看自己加的一些群,常常会有人问为啥这个游戏一更新就要重新下载,而 ...
- Atitit 知识管理的重要方法 数据来源,聚合,分类,备份,发布 搜索
Atitit 知识管理的重要方法 数据来源,聚合,分类,备份,发布 搜索 1.1. Rss 简易信息聚合(也叫聚合内容 Really Simple Syndication1 1.1. Rss 简易信息 ...
随机推荐
- java日志框架与日志系统
日志框架:提供日志调用的接口,实际的日志输出委托给日志系统实现. JCL(Jakarta Commons Logging):比较流行的日志框架,很多框架都依赖JCL,例如Spring等. SLF4j: ...
- Kakfa揭秘 Day5 SocketServer下的NIO
Kakfa揭秘 Day5 SocketServer下的NIO 整个Kafka底层都是基于NIO来进行开发的,这种消息机制可以达到弱耦合的效果,同时在磁盘有很多数据时,会非常的高效,在gc方面有非常大的 ...
- ARM-Linux S5PV210 UART驱动(2)---- 终端设备驱动
在Linux中,UART串口驱动完全遵循tty驱动的框架结构,但是进行了底层操作的再次封装,所以先介绍tty终端设备驱动. 一.终端设备 1.串行端口终端(/dev/ttySACn) 2.伪终端(/d ...
- 用minicom 产看 usb的串口
1 用命令 sudo apt-get install minicom 安装 2 用 minicom -s 进行配置 往下选择 Seral port setup: 然后输入 A :选择自己的 ...
- 转 在无法通过yum下载非标准包时,怎么办
在CentOS下,我们可以通过yum来下载或更新rpm包,但是标准的源(repository)里只提供一部分的rpm包,虽然大部分情况下,这些包是够用的.但是有时候还是需要下载其他的一些非标准的包,如 ...
- Linux进程间通信IPC学习笔记之消息队列(SVR4)
Linux进程间通信IPC学习笔记之消息队列(SVR4)
- jQuery ajax 实现分页 kkpager插件
代码片段一: <!--分页组件 JS CSS 开始--> <!--分页组件 CSS--> <link type="text/css" href=&qu ...
- EXTJS 4.2 资料 将store 传到后台
var lstAddRecord = new Array(); store.each(function (record) { lstAddRecord.push(record.data); }); E ...
- Android中Google地图路径导航,使用mapfragment地图上画出线路(google map api v2)详解
在这篇里我们只聊怎么在android中google map api v2地图上画出路径导航,用mapfragment而不是mapview,至于怎么去申请key,manifest.xml中加入的权限,系 ...
- 在系统方法中调用navigationController的标准写法
在系统方法中调用navigationController的标准写法 -(void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animat ...