【题解】清北学堂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