【8.14校内测试】【DP专题】
nlogn做法,dp[i]表示当前长度为i的最长上升子序列末尾元素的值。
不会写lower_bound(qwq,贴一个以前的好看点的代码
#include<iostream>//使用lower_bound()函数
#include<algorithm>
#include<cstdio>
using namespace std;
int a[],d[],n,len=;
int main()
{
scanf("%d",&n);
for (int i=;i<=n;i++)
scanf("%d",&a[i]);
d[++len]=a[];
for (int i=;i<=n;i++)
if (a[i]>d[len])d[++len]=a[i];
else
{
int x=lower_bound(d+,d+len+,a[i])-d;
d[x]=a[i];
}
printf("%d\n",len);
return ;
}
法一:用度数计算,可以证明最后答案等于选出的k个点的总度数-2*(k-2)-2,表示选择的一条链上去掉两头每个点少减两个度数,两头少减一个度数,就算有分叉也不影响。然后题目转换为求连续的k个点使他们的度数和最小。定义dp[u][k]表示以u为根的子树中选择k个点能获得的最小度数和(包括自己。背包转移。
大佬zyl的代码:
#include<stdio.h>
#include<cstring> const int MAXN = ; inline int min(int a, int b) {
return a < b ? a : b;
} struct Edge {
int to;
Edge *nxt;
} pool[MAXN * ], *head[MAXN], *tail = pool; inline void addEdge(int from, int to) {
Edge *it = tail++;
it -> to = to;
it -> nxt = head[from], head[from] = it;
} int n, k, ans;
int dp[MAXN][MAXN], size[MAXN], w[MAXN]; void dfs(int u, int fa) {
dp[u][] = , dp[u][] = w[u], size[u] = ;
for(Edge *it = head[u]; it; it = it -> nxt) {
int v = it -> to;
if(v == fa) continue;
dfs(v, u);
for(int i = size[u]; i >= ; i--)
for(int j = ; j <= size[v] && i + j <= k; j++)
if(i + j != )
dp[u][i + j] = min(dp[u][i + j], dp[u][i] + dp[v][j]);
size[u] += size[v];
} ans = min(ans, dp[u][k]);
} int main() {
freopen("isolate.in", "r", stdin);
freopen("isolate.out", "w", stdout); scanf("%d%d", &n, &k);
for(int i = ; i < n; i++) {
int u, v; scanf("%d%d", &u, &v);
addEdge(u, v), addEdge(v, u);
w[u]++, w[v]++;
} memset(dp, / , sizeof(dp));
ans = 0x7fffffff; dfs(, ); printf("%d", ans - k * + );
}
法二:定义dp[u][k]表示以u为根的子树中选择k个点最少需要割掉的边。同样是背包转移,如果儿子不选,dp[u][j]就要加一。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std; int n, k; const int N = ; int stot, tov[N*], nex[N*], h[N];
void add ( int u, int v ) {
tov[++stot] = v;
nex[stot] = h[u];
h[u] = stot;
} int siz[N], dp[N][N]; void dfs ( int u, int f ) {
siz[u] = ;
for ( int i = h[u]; i; i = nex[i] ) {
int v = tov[i];
if ( v == f ) continue;
dfs ( v, u );
siz[u] += siz[v];
}
dp[u][] = ;
for ( int i = h[u]; i; i = nex[i] ) {
int v = tov[i];
if ( v == f ) continue;
for ( int j = min ( k, siz[u] ); j; j -- ) {
dp[u][j] = dp[u][j] + ;
for ( int p = ; p <= min ( j, siz[v] ); p ++ ) {
dp[u][j] = min ( dp[u][j], dp[v][p] + dp[u][j-p] );
}
}
}
} int main ( ) {
freopen ( "isolate.in", "r", stdin );
freopen ( "isolate.out", "w", stdout );
scanf ( "%d%d", &n, &k );
for ( int i = ; i < n; i ++ ) {
int u, v;
scanf ( "%d%d", &u, &v );
add ( u, v );
add ( v, u );
}
memset ( dp, 0x3f3f3f3f, sizeof ( dp ) );
dfs ( , );
int ans = dp[][k];
for ( int i = ; i <= n; i ++ )
ans = min ( ans, dp[i][k] + );
printf ( "%d", ans );
return ;
}
真的难受...以前写过当时秒掉的题,今天调了两个小时打死调不出来...【注意!!】像这种求方案数的状压dp通常是需要转移不放的情况的!!少了两句话直接就爆零了...
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std; int r, c;
long long dp[][<<]; int main ( ) {
freopen ( "domino.in", "r", stdin );
freopen ( "domino.out", "w", stdout );
scanf ( "%d%d", &r, &c );
int now = ;
int l = max ( r, c ), p = min ( r, c );
r = p, c = l;
int tot = ( << r ) - ;
dp[now][tot] = ;
int pre = ( << ( r - ) );
for ( int i = ; i <= c; i ++ )
for ( int j = ; j <= r; j ++ ) {
now ^= ;
memset ( dp[now], , sizeof ( dp[now] ) );
for ( int s = ; s <= tot; s ++ ) {
int up = s & pre;
int las = s & ;
if ( !up ) {
int ss = s << | ;
dp[now][ss] += dp[now^][s];
}
if ( up && !las ) {
if ( j != ) {
int ss = ( s ^ pre ) << | ;
dp[now][ss] += dp[now^][s];
}
int ss = ( s ^ pre ) << ;
dp[now][ss] += dp[now^][s];
}
if ( up && las ) {
int ss = ( s ^ pre ) << ;
dp[now][ss] += dp[now^][s];
}
}
}
printf ( "%I64d", dp[now][tot] );
return ;
}
实际上是一道比较简单的背包了...定义dp[k][p]表示子集s的和为k时s2的值为p的状态能否到达。如果dp[j][p]为true,dp[j+c[i]][p+c[i]]和dp[j+c[i]][p]都为true。【注意】当p>j时,dp[j+c[i]][p]依然需要转移!
#include<iostream>
#include<cstdio>
using namespace std; int n, k, c[];
int dp[][]; int main ( ) {
freopen ( "coin.in", "r", stdin );
freopen ( "coin.out", "w", stdout );
scanf ( "%d%d", &n, &k );
for ( int i = ; i <= n; i ++ )
scanf ( "%d", &c[i] );
dp[][] = ;
for ( int i = ; i <= n; i ++ ) {
for ( int j = k-c[i]; j >= ; j -- )
for ( int p = k; p >= ; p -- ) {
if(p<=k-c[i])
dp[j+c[i]][p+c[i]] |= dp[j][p];
dp[j+c[i]][p] |= dp[j][p];
}
}
int ans = ;
for ( int i = ; i <= k; i ++ )
if ( dp[k][i] ) ans ++;
printf ( "%d\n", ans );
for ( int i = ; i <= k; i ++ )
if ( dp[k][i] ) printf ( "%d ", i );
return ;
}
可能是今天考了四道题的原因,做的过程中有点慌,一直死扣t2和t3导致最后没有时间看t4,t3这种类型下次一定不能再错了!!
【8.14校内测试】【DP专题】的更多相关文章
- 【8.30校内测试】【找规律模拟】【DP】【二分+贪心】
对于和规律或者数学有关的题真的束手无策啊QAQ 首先发现两个性质: 1.不管中间怎么碰撞,所有蚂蚁的相对位置不会改变,即后面的蚂蚁不会超过前面的蚂蚁或者落后更后面的蚂蚁. 2.因为所有蚂蚁速度一样,不 ...
- 树形dp专题总结
树形dp专题总结 大力dp的练习与晋升 原题均可以在网址上找到 技巧总结 1.换根大法 2.状态定义应只考虑考虑影响的关系 3.数据结构与dp的合理结合(T11) 4.抽直径解决求最长链的许多类问题( ...
- 决策单调性优化dp 专题练习
决策单调性优化dp 专题练习 优化方法总结 一.斜率优化 对于形如 \(dp[i]=dp[j]+(i-j)*(i-j)\)类型的转移方程,维护一个上凸包或者下凸包,找到切点快速求解 技法: 1.单调队 ...
- 状压dp专题复习
状压dp专题复习 (有些题过于水,我直接跳了) 技巧总结 : 1.矩阵状压上一行的选择情况 \(n * 2^n\) D [BZOJ2734][HNOI2012]集合选数 蒻得不行的我觉得这是一道比较难 ...
- 区间dp专题练习
区间dp专题练习 题意 1.Equal Sum Partitions ? 这嘛东西,\(n^2\)自己写去 \[\ \] \[\ \] 2.You Are the One 感觉自己智力被吊打 \(dp ...
- 测试开发专题:spring-boot自定义异常返回
上文测试开发专题:spring-boot统一异常捕获我们讨论了java异常以及如何使用Spring-Boot捕获异常,但是没有去说捕获异常后该如何进一步处理,这篇文章我们将对这个遗留的问题进行讨论. ...
- 【8.31校内测试】【找规律二分】【DP】【背包+spfa】
打表出奇迹!表打出来发现了神奇的规律: 1 1 2 2 3 4 4 4 5 6 6 7 8 8 8 8 9 10 10 11 12 12 12 13 14 14 15 16 16 16 16 16.. ...
- 【11.8校内测试】【倒计时2天】【状压DP】【随机化?/暴力小模拟】
Solution 数据范围疯狂暗示状压,可是一开始发现状态特别难受. 将每一层的奇偶性状压,预处理所有状态的奇偶性.每一层的输入代表的其实可以是下一层某个点可以被从这一层哪些点转移到. 所以枚举每个状 ...
- 【11.5校内测试】【倒计时5天】【DP】【二分+贪心check】【推式子化简+线段树】
Solution 非常巧妙的建立DP方程. 据dalao们说题目明显暗示根号复杂度??(反正我是没看出来 因为每次分的块大小一定不超过$\sqrt n$,要不然直接每个位置开一个块答案都才为$n$. ...
随机推荐
- 【逆向知识】PE ASLR
1.知识点 微软从windows vista/windows server 2008(kernel version 6.0)开始采用ASLR技术,主要目的是为了防止缓冲区溢出 ASLR技术会使PE文件 ...
- 一个不错的linux学习资料下载的网址
本文比较完整的讲述GNU make工具,涵盖GNU make的用法.语法.同时重点讨论如何为一个工程编写Makefile.作为一个Linux程序员,make工具的使用以及编写Makefile是必需的. ...
- Oracle和MySQL的高可用方案对比【转】
关于Oracle和MySQL的高可用方案,其实一直想要总结了,就会分为几个系列来简单说说.通过这样的对比,会对两种数据库架构设计上的细节差异有一个基本的认识.Oracle有一套很成熟的解决方案.用我在 ...
- Html.DropDownListFor() 二级联动 ($.getJSON)
Control: public ActionResult GetPositionName(int parentid) //发布新职位页面中的根据职位类别,获取职位名称 { List<Catego ...
- Python之 Lambda表达式
标签(空格分隔): Python进阶 Lambda是一种匿名函数,当我们需要重复调用某一函数,又不想写那么多代码时可以使用lambda表达式来代替. lambda的通用格式: lambda argum ...
- centos7.2系统没有eth0网卡
最近一直在学centos7.5系统,偶然看到虚拟机里有7.2系统所以想练习一下(其实7.2和7.5差不多),但是打开虚拟机之后,发现没有eth0网卡 那没有eth0网卡就无法远程连接ssh,既然遇到了 ...
- 基于timestamp和nonce的防止重放攻击方案
参考:http://blog.csdn.net/koastal/article/details/53456696
- FM的推导原理--推荐系统
FM:解决稀疏数据下的特征组合问题 Factorization Machine(因子分解机) 美团技术团队的文章,觉得写得很好啊:https://tech.meituan.com/deep-unde ...
- java基础29 迭代器 listIterator() 及各种遍历集合的方法
listIterator() 迭代器包含了 Iterator() 迭代器中的所有方法. 1.ListIterator的常用方法 hasPrevious() :判断是否还有上一个元素,有则返回true ...
- SQL语句添加删除修改字段[sql server 2000/2005]
用SQL语句添加删除修改字段1.增加字段 alter table docdsp add dspcodechar(200)2.删除字段 ALTER TABLE table_NAME ...