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 简易信息 ...
随机推荐
- php substr,iconv_substr,mb_substr
php进行中文字符串的截取时,会经常用到二个函数iconv_substr和mb_substr,对这二个函数应该如何选择呢?参考下本文介绍的例子就明白了. 示例代码,用到了函数substr与iconv_ ...
- PhantomJS实现最简单的模拟登录方案
以前写爬虫,遇到需要登录的页面,一般都是通过chrome的检查元素,查看登录需要的参数和加密方法,如果网站的加密非常复杂,例如登录qq的,就会很蛋疼 在后面,有了Pyv8,就可以把加密的js文件扔给它 ...
- div中加入iframe,可以实现Ajax的功能
div中加入iframe,可以实现Ajax的功能,如果查询的时候,比如说城市的选择,用Ajax去实现, 在.net 可以考虑用UpdatePanel,但是点击了查询刷新表格(表格需要重新刷新加载,非纯 ...
- 进程(Process)和线程(Thread)的关系和区别
Definition定义-------------Process进程是应用程序的一次运行活动:从操作系统核 心角度来说,进程是操作系统分配和调度系统内存资源.cpu时间片等资源的基本单位,为正在运行的 ...
- sql中的inner join, left join, right join的区别
下面介绍一下 inner join, left join, right join这者之间的区别 现在我假设有A表和B表 left join select * from A a left join B ...
- shell 实现word count
awk '{arr[$2]+=$1}END{for (i in arr) print i,arr[i]}' sort_all.txt | sort -k2nr -g
- css3 简单界面动画
asdasdasdasda asdasdasdasda
- CSS定义字体间距 字体行与行间距
CSS定义字体行间距 line-height:xxpx; CSS定义字体间距 下面我们讲述一下CSS的文本属性,还是先来看一下文本属性的详细列表: 属性 属性含义 属性值 Word-s ...
- 简单3d RPG游戏 之 004 攻击(一)
功能:实现点击键盘F键,怪物血量条减少,并且假定是近战,需要对距离进行判断,距离小于一定值的时候按F才会减少怪物的血条. 新建c#脚本PlayerAttack,绑定到Player,并在unity里将敌 ...
- 如果Android和C#在一起?
先看两则新闻. 一则来自新浪科技: 谷歌上诉遭拒绝 需向甲骨文支付Java使用费 大意是说,针对谷歌Android操作系统侵犯甲骨文Java知识产权的指控,美国法院最近做出了有利于甲骨文的裁决 ...