其他分享
首页 > 其他分享> > 【题解】清北学堂DP营考试

【题解】清北学堂DP营考试

作者:互联网

清北学堂DP营考试

共4题,全部为DP题,AC第一题,第二题60,第三题骗到10,第4题骗到20

T1签到题

T2练习题

状态

f[i ] [j ] [r ]选到第i个数,选了j个数了,第一个数选的是第r个数(没错我也是这么想的)

转移

枚举上一个数t

f[i] [j + 1] [r] = max{f[t] [j] [r] + abs(a[t] - a[i])};

CaO

这个题n^4是可以过的,但是我才60,zhx:"写错了呗"

T3骗分题

复杂度

n <= 16说明是3 ^ n 的做法,所以状压(好像讲状压时我写语文来着)

状态1(正常人除了我这样的菜鸡应该会这样设计状态但是这是不对的)

f[i],i是一个n位二进制数,表示使得i所对应的集合里所有人都合法的最少交换次数。所谓i所对应的集合,是指这一位是1的人所组成的集合。交换只能在集合内部进行。

QAQ这个玩意没法转移

状态2(这是对的!)

如果有解,答案的上限是n - 1。

判断有无解:把所有的属性值拎出来,共2 * n个,从小到大排序,最优(使每一组两个数之差最小)的组合方案是相邻的两个数两两结合。然后依次判断,如果有某一组不满足两数绝对值之差小于等于c,那么就没有解。cout << -1;

交换:

如果说分成两部分,左边m人,右边n - m人

如果左边内部可以通过内部交换合法,左边要操作m - 1次,右边内部也可以通过内部交换合法,要用n - m - 1次,那么左右合并,共n - 2次操作

如果能分成3组,总操作就是n-3次

分成4组就更好了,越多越好

状态来了:

就像状压DP一直做的那样,用数i表示一个集合,某一位是1,表明这个人在集合内

f[i]表示集合里的人最多能分成几组,满足每组内部可以自行交换合法

转移

f[i] = max(f[s]+f[i - s])

最后的答案:n - f[2 ^ n - 1]

初始化

就是相邻的两个数b和b+1也就是一组,如果满足差的绝对值小于等于c,f[i] = 1

技巧

先确定答案的上界,反推出这个上界带来的性质

T4是个啥

暴力有40分,枚举所有排列

90分做法

max_a = max{a1, a2...an}

最优解里面所有a的值最大为max_a

分别给a,b,c从小到大排序,得到:

a'_1,a'_2...a'_n

b'_1,b'_2,...b'_n

c'_1,c'_2,...c'_n

状态

f[i] [j] [k] 表示已经选最多的三元组,[旧状态:选了若干个三元组(不知道几个),无法确定某个三元组是否已选]这些三元组里面a最大为a‘_i,b最大为b’_j,c最大为c'_k的时候,所需的最小代价

选了一组:

什么样的三元组没被选过:

(a_r, b_r, c_r)满足a_r > a'_i或b_r > b'_j或c_r > c'_k

如果a_r <= a_i'&& b_r <= b_j' && c_r <= c_k',那这个三元组一定已选[如果是旧状态:只能说明有可能已选]

答案

f[n] [n] [n]

转移

就是不断地选呗

枚举1 <= r <= n,没选就选上,a_r > a'_i或b_r > b'_j或c_r > c'_k的就是没选过的

f[i] [j] [k] ->f[max(i,x)] [max(j, y)] [max(k, t)] 其中a_r = a'_x, b_r = b'_y, c_r = c'_t(就是找到这个a_r从小到大排第x)

设为f[x'] [y'] [t']

我们选上了第r个三元组,但是不仅仅选了它一个,所有转移后满足现在的条件的三元组都加入了

因为我们的定义是下一个加入的是第r个,所以其余的新加入的成员都要接在第r个后面

加入之后,这些所有的三元组必须变成(a'(x'), b'(y'), c'(t')),新增的代价就是m*(a'(x') - a'i) + m*(b'(y') - b'j) + m *(c'(t') - c'_k)

其中m是新加入的三元组的个数

前缀和O(1)转移

复杂度

O(n^4)

100分做法(n^3)

同样的状态

转移

一个数一个数地加,一个三元组分3次加,根据添加顺序得到一个3 *n 的排列

只有三个数都被加入的三元组才算被加进去,我们要看看一个三元组的最后一个数是何时被加入的

//伦无语次

算了放弃这个正解,明年再看吧

标签:...,状态,题解,三元组,max,集合,清北,DP
来源: https://www.cnblogs.com/ZhengkunJia/p/12639021.html