在这里记录一些在大神们的博客,以及自己做过的一些DP的神奇思路吧

1.2015/04 NEUQ 月赛  转自:http://zyfzyf.is-programmer.com/posts/89993.html

 E.又被DP卡住了。

  感觉是必须记录和的具体差值的。因为只有最值无法保证子问题最优的性质。

  当然如果既记录具体差值,又记录交换了多少次的话不仅MLE而且TLE。

  然后我就弃疗了,觉得一定是防AK神题!

  然后学姐发了题解,顿时感觉好巧妙啊。

  我们只记录上面的和。用f[i][j]表示前i个数组成和为j最少需要交换多少次,这个满足子问题最优的性质,而且可以很简单的DP。

  太神了,Orz!

  这次是败在了状态的设计上,以后要多下功夫。(好像脑袋里闪过这个思路?但立马被否决了?)

因为E比较好,所以搬运一下题面:
陈船长和xzx每人都有N个玩具,序号从1到N。不同的玩具可能并不一样好玩。
其中陈船长的第i个玩具的好玩度为C[i],xzx的第i个玩具的好玩度为X[i], 好玩度可以是负数,可以理 解为不好玩的程度。
你可以交换陈船长的第i个玩具和xzx的第i个玩具,为了让他们两个玩的尽可能一样高兴,他们希望经过 不大于K次交换后陈船长所有玩具的好玩度总和与xzx的总和之差的绝对值最小,即 |Sum(C) - Sum(X)| 最小。现在,请你告诉他俩最小值是多少。
多组测试数据,第一行一个整数T(T < ), 表示测试数据组数。
每组数据第一行两个整数N( < N < ), K( < K <= N)。
接下来一行N个整数,第i个数代表C[i](- <= C[i] <= )。
再接下来一行N个整数, 第i个数代表X[i](- <= X[i] <= )。
数组下标从0开始。 比赛地址

2. 【模拟试题1】【20150514】

三种物品的背包:

    1. $v(x)=A*x^2-B*x$ 价值随所分配的体积的变化而变化……

    2. 多重背包

    3. 完全背包

  其实是个傻逼题,因为数据规模小,暴力就能过,然而由于没见过第一种物品的价值函数,加上题目描述不清楚,所以自己傻逼了(不知道怎么乱搞了一下,得了70分)

  其实第一种物品就暴力枚举每一个物品我们分配给它多少空间就可以,“每个体积的甲类物品只有一个”TM就是在误导人!

  不过倒是学习了一种新的写背包的姿势~

 //2015_05_14 pack
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
typedef long long LL;
inline int getint(){
int r=,v=; char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-;
for(; isdigit(ch);ch=getchar()) v=v*-''+ch;
return r*v;
}
const int N=,M=;
/*******************template********************/
int n,m;
LL f[M]; void solve1(int a,int b){
D(j,m,) F(i,,j)
f[j]=max(f[j],f[j-i]+a*i*i-b*i);
}
void zeroone(int a,int b){
D(j,m,b)
f[j]=max(f[j],f[j-b]+a);
}
void solve2(int a,int b,int c){
int k=;
while(c>=(<<k)){
zeroone(a*(<<k),b*(<<k));
c-=(<<k);
k++;
}
if (c) zeroone(a*c,b*c);
}
void solve3(int a,int b){
F(j,b,m)
f[j]=max(f[j],f[j-b]+a);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("pack.in","r",stdin);
freopen("pack.out","w",stdout);
#endif
n=getint(); m=getint();
F(i,,n){
int x=getint(), A=getint(), B=getint(),C;
if (x==){
solve1(A,B);
}else if (x==){
C=getint();
solve2(A,B,C);
}else{
solve3(A,B);
}
}
printf("%d\n",f[m]);
return ;
}

3. 【BestCoder】【Round#41】【BZOJ】【3612】【HEOI 2014】平衡

整数拆分的DP姿势= =

  f[i][j]表示将 i 拆成 j 个不同的数(均不超过n)的方案数

  f[i][j]=f[i-j][j]+f[i-j][j-1]

  if (i>n+1) f[i][j]-=f[i-(n+1)][j-1](相当于去掉了最后那一列/一个数(n+1))

4.【BZOJ】【1089】【SCOI2003】严格n元树

  f[i]=f[i-1]^n+1 f[i]表示深度小于等于 i 的严格n元树的数目

  ans=f[d]-f[d-1] //这个表达式感觉好神……

5.【BZOJ】【2750】【HAOI2012】Road&& CTSC D1T1 好朋友

  拓扑序DP,然而2750这题的DP是较简单的一个,统计每条边在多少条最短路径上……其实可以统计 有多少条最短路径经过了x,以及y出发到达任意一个结束点有多少种走法(沿最短路)

  我们可以用Dijkstra求出以 i 为起点的最短路径图,它是一个DAG,然后我们用dij扩展的顺序(一个拓扑序)来搞DP!

  令a[x]表示从 i 沿最短路走到 x 的方案数,b[x]表示从 x 往出走,沿最短路走到任意一个结束结点的总方案(就是经过x的最短路条数?只不过只看后半段)

  而CTSC的我还没搞出来……

UPD:

  答案表达式是这样的:$$ ans[v]=\sum_{s \not = v \not =t} \frac{a[s]*a[t]*\sigma_{s,t}(v)}{\sigma_{s,t}} $$

  f1[x]表示从S到x的最短路宽度,然后我们需要处理的是最短路的后一半。。

  如果没有分母那个东西,f2[x]应该是 $\sum (f2[to[i]]+a[to[i]])*width[i] $

  然而分母和分子是不可以分开搞的……

  但是分母其实我们已经算出来了!!就是f1[x]!(我是sb一直没想到……)

  所以维护f2[x]还是很容易……$f2[x]=\sum (f2[to[i]]+\frac{a[to[i]]}{f1[to[i]]})*width[i]$

  sad....我需要吃药。。。脑残片QAQ

 /**************************************************************
Problem: 4055
User: Tunix
Language: C++
Result: Accepted
Time:6976 ms
Memory:1520 kb
****************************************************************/ #include<queue>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
typedef long long LL;
inline int getint(){
int r=,v=; char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-;
for(; isdigit(ch);ch=getchar()) v=v*-''+ch;
return r*v;
}
//#define debug
const int N=,M=,INF=;
/*******************template********************/ typedef long double db;
int head[N],next[M<<],to[M<<],len[M<<],cnt;
db b[M<<];
void ins(int x,int y,int z,db wd){
to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt; len[cnt]=z; b[cnt]=wd;
}
void add(int x,int y,int z,db wd){
ins(x,y,z,wd); ins(y,x,z,wd);
}
int n,m,a[N];
typedef pair<int,int> pii;
#define mp make_pair
priority_queue<pii,vector<pii>,greater<pii> >Q;
int c[N],d[N],vis[N];
db ans[N],f1[N],f2[N]; void Dij(int S){
F(i,,n) d[i]=INF,vis[i]=,c[i]=;
d[S]=; Q.push(mp(,S));
int t=;
while(!Q.empty()){
int x=Q.top().second; Q.pop();
if (vis[x]) continue;
vis[x]=++t;
for(int i=head[x];i;i=next[i])
if (d[to[i]]>d[x]+len[i]){
d[to[i]]=d[x]+len[i];
Q.push(mp(d[to[i]],to[i]));
}
}
F(i,,n) f1[i]=f2[i]=; f1[S]=;
F(i,,n) c[vis[i]]=i;
// F(i,1,t) printf("%d ",c[i]); puts("");
F(i,,t){
int x=c[i];
for(int j=head[x];j;j=next[j])
if (d[to[j]]==d[x]+len[j]) f1[to[j]]+=f1[x]*b[j];
}
D(i,t,){
int x=c[i];
for(int j=head[x];j;j=next[j])
if (d[to[j]]==d[x]+len[j])
f2[x]+=b[j]*(f2[to[j]]+(db)a[to[j]]/(db)f1[to[j]]);
}
F(i,,n) if (i!=S) ans[i]+=(db)a[S]*f1[i]*f2[i];
}
int main(){
#ifndef ONLINE_JUDGE
freopen("misc.in","r",stdin);
freopen("misc.out","w",stdout);
#endif
n=getint(); m=getint();
F(i,,n) a[i]=getint();
F(i,,m){
int x=getint(),y=getint(),z=getint();
double t1; scanf("%lf",&t1);
add(x,y,z,t1);
}
F(i,,n)
Dij(i);
F(i,,n){
double x=ans[i];
printf("%.9f\n",x);
}
return ;
}

(CTSC D1T1)

6.树形DP【模拟试题3】【20150527】

  (1)树形状压DP,其实在看题解之前我似乎并没有搞懂这题在干什么……

  对于节点 i ,我们考虑f[i][j]表示 i 这棵子树中,分部包含情况为 j 的最大收益,因为一个分部管的是从x到根的所有点,所以对于一个点来说,管它的就是子树中的所有分部,所以就可以dp啦~依次枚举每个儿子的子树中有哪些分部,用一个辅助数组,我们可以搞:

  c[j]=f[x][j];

  c[j]=max(c[j],f[y][k]+f[x][j^k]);

  f[x][j]=c[j];

依次搞下来即可。

  初始化就是分部全部在 x 节点。计算完后要加上符合的收益(T种中的某一些……)

  (2)无向图最大权路径覆盖= =?然而其实并不是费用流之类……

  f[x][0]表示x是孤立点时,x子树内最大收益;

  f[x][1]表示x子树内有一条链与它相连;

  f[x][2]表示x子树内有两条链与它相连

  前两种情况是可以继续向上连的,而第三种情况就不可以了……

  转移……Orz regina8023 其实是个贪心。

  先假设所有点都没跟x连,得到f[x][0],然后再考虑一下将某个儿子连到父亲,会使答案改变多少,贪心地选出1-2个,即可得到f[x][1]和f[x][2]。

  感觉这个先假设全选、【求差】然后在差值中选最优的思路好神啊。。。(其实是我太弱了没见过

7.【BZOJ】【2878】【NOI2012】迷失游乐园

  期望&树形&基环树DP的好题QAQ,题解太长我就不复制了,感觉这个先求出来down再求up的方法好神奇……

8.【TYVJ 五月图论专项有奖比赛】

  第三题:求树的双重心?。。。树形dp很神奇,Orz zyf。

  枚举断掉的点,然后找最大的儿子往过走,更新答案。。。QwQ说不清了

9.【BZOJ】【4145】【AMPPZ2014】The Prices

  状压->01背包

DP思路的更多相关文章

  1. Codeforces 1204D2. Kirk and a Binary String (hard version) (dp思路)

    题目链接:http://codeforces.com/contest/1204/problem/D2 题目是给定一个01字符串,让你尽可能多地改变1变为0,但是要保证新的字符串,对任意的L,R使得Sl ...

  2. 洛谷P1244 青蛙过河 DP/思路

    又是一道奇奇怪怪的DP(其实是思路题). 原文戳>>https://www.luogu.org/problem/show?pid=1244<< 这题的意思给的挺模糊,需要一定的 ...

  3. 很好的DP思路,字符串比较次数

    题目: https://leetcode.com/problems/distinct-subsequences/?tab=Description 一般没有明显思路的情况下,都要想想DP,用下Divid ...

  4. BZOJ.3227.[SDOI2008]红黑树tree(树形DP 思路)

    BZOJ orz MilkyWay天天做sxt! 首先可以树形DP:\(f[i][j][0/1]\)表示\(i\)个点的子树中,黑高度为\(j\),根节点为红/黑节点的最小红节点数(最大同理). 转移 ...

  5. 洛谷P2362 围栏木桩----dp思路

    在翻dp水题的时候找到的有趣的题0v0 原文>>https://www.luogu.org/problem/show?pid=2362<< 题目描述 某农场有一个由按编号排列的 ...

  6. AGC033 D~F——[ 值放到角标的DP ][ 思路+DP ][ 思路 ]

    地址:https://atcoder.jp/contests/agc033/ D Complexity dp[ i ][ j ][ k ][ l ] 表示左上角是 ( i , j ) .右下角是 ( ...

  7. [状压DP思路妙题]图

    源自 luhong 大爷的 FJ 省冬令营模拟赛题 Statement 给定一个 \(n\) 个点 \(m\) 条边的图,没有重边与自环 每条边的两端点编号之差不超过 \(12\) 求选出一个非空点集 ...

  8. ZOJ 3647 Gao the Grid dp,思路,格中取同一行的三点,经典 难度:3

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4837 三角形的总数=格子中任取3个点的组合数-同一横行任取3个点数目-同一纵行 ...

  9. BZOJ.1566.[NOI2009]管道取珠(DP 思路)

    BZOJ 洛谷 考虑\(a_i^2\)有什么意义:两个人分别操作原序列,使得得到的输出序列都为\(i\)的方案数.\(\sum a_i^2\)就是两人得到的输出序列相同的方案数. \(f[i][j][ ...

随机推荐

  1. jquery获取浏览器各种高宽

    $(document).ready(function(){ alert($(window).height()); //浏览器当前窗口可视区域高度 alert($(document).height()) ...

  2. 007.LVM查看命令

    一 PV查看 [root@kauai ~]# pvdisplay #显示有关物理卷的信息 --- Physical volume --- PV Name /dev/sdb5 #PV名称 VG Name ...

  3. codeforces-1080C

    title: codeforces-1080C date: 2018-11-25 14:23:53 tags: acm 刷题 categories: Codeforces https://www.cn ...

  4. java中关于锁知识的整理

    1.1什么是锁? 在计算机科学中,锁(lock)或互斥(mutex)是一种同步机制,用于在有许多执行线程的环境中强制对资源的访问限制.锁旨在强制实施互斥排他.并发控制策略. 锁通常需要硬件支持才能有效 ...

  5. SpringMVC(八) RequestMapping HiddenHttpMethodFilter

    SpringMVC隐藏方法: 使用PUT和DELETE方法.默认HTML支持GET和POST方法.通过HiddenHttpMethodFilter将POST转成PUT和DELETE方法. 1.将Hid ...

  6. android 的安全问题

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha 1,webView的js脚本引发的安全 2,代码的混淆加密.还可采用第三方apk加固程序 ...

  7. bzoj3111: [Zjoi2013]蚂蚁寻路

    题目链接 bzoj3111: [Zjoi2013]蚂蚁寻路 题解 发现走出来的图是一向上的凸起锯齿状 对于每个突出的矩形dp一下就好了 代码 /* */ #include<cstdio> ...

  8. PHP 从基础开始 ——重要知识点笔记

    PHP static 关键词 通常,当函数完成/执行后,会删除所有变量.不过,有时我需要不删除某个局部变量.实现这一点需要更进一步的工作. 要完成这一点,请在您首次声明变量时使用 static 关键词 ...

  9. pygame系列_font游戏字体_源码下载

    在pygame游戏开发中,一个友好的UI中,漂亮的字体是少不了的 今天就给大伙带来有关pygame中字体的一些介绍说明 首先我们得判断一下我们的pygame中有没有font这个模块 if not py ...

  10. 喵哈哈村的魔法考试 Round #5 (Div.2) 题解

    老规矩 有问题直接联系我:475517977@qq.com A 直接暴力的for一遍,统计连续的有多少个就好了.模拟题. #include<bits/stdc++.h> using nam ...