CF1354F Summoning Minions

考虑我们一定是先放我们选定了\(m\)个数,一定是先放了\(m-1\)个数上去,然后让放上一个不打算选的然后拿下来,白嫖\(b * (m-1)\)的贡献,最后放上一个打算放的。
考虑我们一定是按\(b\)的顺序放的。
\(b\)排序,用动态规划解决即可。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define ll long long 
#define N 80

ll f[N][N],last[N][N];
ll used[N];

struct P{int a,b,id;}e[N];

bool operator < (P x,P y){return x.b < y.b;}

ll T;

inline void dfs(int i,int j){
	if(!i)return;
	if(last[i][j])dfs(i - 1,j - 1),used[i] = 1;
	else
	dfs(i - 1,j),used[i] = 0;
}

int main(){
	scanf("%lld",&T);
	while(T -- ){
		ll n,m;
		std::memset(f,0,sizeof(0));
		scanf("%lld%lld",&n,&m);
		for(int i = 1;i <= n;++i){
			scanf("%d%d",&e[i].a,&e[i].b);
			e[i].id = i;
		}
		std::memset(f,-0x3f,sizeof(f));
		f[0][0] = 0;
		std::sort(e + 1,e + n + 1);
		for(int i = 1;i <= n;++i)
		for(int i = 1;i <= n;++i)
		for(int j = 0;j <= std::min(i,(int)m);++j){
			f[i][j] = f[i - 1][j] + e[i].b * (m - 1);
			last[i][j] = 0;
			if(j && (f[i][j] <= f[i - 1][j - 1] + e[i].a + e[i].b * (j - 1)))
			f[i][j] = f[i - 1][j - 1] + e[i].a + e[i].b * (j - 1),last[i][j] = 1;
		}
		dfs(n,m);
		std::vector<int>QWQ;
		for(int i = 1;i <= n;++i)
		if(used[i])QWQ.push_back(e[i].id);
		std::cout<<m + (n - m) * 2<<std::endl;
		for(int i = 0;i < QWQ.size() - 1;++i)
		std::cout<<QWQ[i]<<" ";
		for(int i = 1;i <= n;++i)
		if(!used[i])
		std::cout<<e[i].id<<" "<<-e[i].id<<" ";
		std::cout<<QWQ[QWQ.size() - 1]<<std::endl;
	}
}
posted @ 2021-08-23 15:32  fhq_treap  阅读(42)  评论(0编辑  收藏  举报