【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$. ...
随机推荐
- Jenkins忘记用户名密码
一.进入C盘.jenkins配置文件中找到config.xml 需要删除一下内容: <useSecurity>true</useSecurity> <authorizat ...
- Jenkins+Ant+TestNG+Testlink自动化构建集成
这段时间折腾自动化测试,之前都是在Eclipse工程里面手工执行自动化测试脚本,调用Testlink API执行测试用例,目前搭建Jenkins自动化构建测试的方式,实现持续构建,执行自动化测试. 硬 ...
- RabbitMQ--work queues(二)
封装一个task到一个message,并发送到queue.consumer会去除task并执行这个task. 这里我们简化了操作,发送消息到队列中,consumer取出消息计算里面'.'号有几个就sl ...
- python网络编程-socket发送大数据包问题
一:什么是socket大数据包发送问题 socket服务器端或者客户端在向对方发送的数据大于对方接受的缓存时,会出现第二次接受还接到上次命令发送的结果.这就出现象第一次接受结果不全,第二次接果出现第一 ...
- python基础--类的经典类vs新式类
经典类VS新式类区别 1)写法新式类class Person(object):#new style 经典类class Persion: #classical style 2)调用父类 新式写法用sup ...
- jQuery选择器详解及实例---《转载》
选择器是jQuery最基础的东西,本文中列举的选择器基本上囊括了所有的jQuery选择器,也许各位通过这篇文章能够加深对jQuery选择器的理解,它们本身用法就非常简单,我更希望的是它能够提升个人编写 ...
- SQL Server 2000 系统存储过程
SQL Server 2000 系统存储过程 在 Microsoft? SQL Server? 中,许多管理和信息活动可以通过系统存储过程执行.系统存储过程按这些分类分组. 分类 描述 Active ...
- c语言双向循环链表
双向循环链表,先来说说双向链表,双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱.所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继 ...
- 树莓派GPIO控制RGB彩色LED灯
树莓派GPIO通过PWM来控制RGB彩色LED灯,可以显示任何我们想要的颜色. RGB模块简介 这个RGB彩色LED里其实有3个灯,分别是红灯.绿灯和蓝灯.控制这三个灯分别发出不同强度的光,混合起来就 ...
- **iOS发JSON请求中字符串加转义,返回的JSON去转义
iOS中使用NSSerialization把对象转为JSON字符串后,多出来反斜杠的问题 http://segmentfault.com/q/1010000000576646 NSDictionary ...