【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$. ...
随机推荐
- 存储过程简单Demo
--创建存储过程 delimiter // create procedure p1() begin end // --调用存储过程 call p1(); --删除存储过程 drop procedure ...
- springcloud的Turbine配置监控多个服务的一些坑!!!!InstanceMonitor$MisconfiguredHostException,No message available","path":"/actuator/hystrix.stream,页面不显示服务或者一直loading
踩了几个小时坑,使用仪表盘监控单个服务的时候很容易,但是一到多个服务,瞬间坑就来了,大概碰到下面三个: 1InstanceMonitor$MisconfiguredHostException, No ...
- 【算法学习】【洛谷】树链剖分 & P3384 【模板】树链剖分 P2146 软件包管理器
刚学的好玩算法,AC2题,非常开心. 其实很早就有教过,以前以为很难就没有学,现在发现其实很简单也很有用. 更重要的是我很好调试,两题都是几乎一遍过的. 介绍树链剖分前,先确保已经学会以下基本技巧: ...
- Pytorch多进程最佳实践
预备知识 模型并行( model parallelism ):即把模型拆分放到不同的设备进行训练,分布式系统中的不同机器(GPU/CPU等)负责网络模型的不同部分 —— 例如,神经网络模型的不同网络层 ...
- 24 The Go image package go图片包:图片包的基本原理
The Go image package go图片包:图片包的基本原理 21 September 2011 Introduction The image and image/color packag ...
- ipad webapp禁止长按选择
1.禁止长按屏幕弹出对话框并选中文字 /*禁止长按选择文字事件*/ * { -webkit-touch-callout: none; -webkit-user-select: none; -khtml ...
- linux(vi)常用命令
常用操作 系统命令 查看主机名 hostname 修改主机名(重启后无效) hostname yang 修改主机名(重启后永久生效) vi /ect/sysconfig/network 修改IP(重启 ...
- MySQL学习笔记:while循环
思考:while循环是否只能使用在存储过程或者存储函数之中,不能直接在查询语句中使用? ———— 循环一般在存储过程和存储函数中使用. 直接放几个例子: 例一: 1.创建存储过程 DELIMITER ...
- Linux--忘记MySQL密码的解决方法和输入mysqld_safe --skip-grant-tables &后无法进入MySQL的解决方法
https://blog.csdn.net/qq_35389417/article/details/78910974
- 提高eclipse使用效率(二)—— 提高Android开发效率的小技巧
XML文件的代码提示 adt中也有xml文件的代码提示,为了让提示来的更加猛烈,我们还要设置一下 打开eclipse - Window - Preferences,在右边的目录树中切换到XML - X ...