21.6.30 t1

tag:状压dp,贪心


屑模拟赛三道题数据全部木大,最高可能得分30

首先要猜想一个结论,除去限定长度,剩下的一定是尽量点满一个技能点。所以最终技能树应该是限定长度的技能+一堆点满的技能+剩下的全部点到一个技能上。

感性证明:如果把某个技能送一个技能点给另外一个技能更优,那么直接把全部点都送过去一定更优(根据题目给定的性质:差分序列严格递增)

然后问题变为,要选出几个点满的技能,还要选出几个固定长度的技能。

假设我们已经选择好了固定长度的技能,那么点满的技能一定是剩下的技能中 \(a_{i,k}\) 最大的几个。

所以按 \(a_{i,k}\) 排序,设 \(f_{i,S}\) 表示前 \(i\) 个,满足的条件集合为 \(S\)

这样做的好处在于,\(i-|S|\) 就表示在前 \(i\) 大的技能中有多少个技能是没有固定长度的,而我们又是按照 \(a_{i,k}\) 排序后从大到小进行dp,所以一定是能选就选。


注意 \(n\) 过大的情况,要和 \(k(m-S)\)\(\min\)

不过不知道数据有没有这种情况。。

这个是可以输出方案的,拿来对拍的代码

这个是过了对拍的代码

#include<bits/stdc++.h>
using namespace std;

template<typename T>
inline void Read(T &n){
	char ch; bool flag=false;
	while(!isdigit(ch=getchar()))if(ch=='-')flag=true;
	for(n=ch^48;isdigit(ch=getchar());n=(n<<1)+(n<<3)+(ch^48));
	if(flag)n=-n;
}

typedef long long ll;

enum{
	MAXN = 200005
};

int n, m, k, S;
ll f[MAXN][1<<6];
int _a[MAXN], *a[MAXN];
int id[MAXN], lim[7];

inline bool cmp(const int &u, const int &v){return a[u][k]>a[v][k];}
inline int val(int x, int y){return y?a[id[x]][y]:0;}

inline void upd(ll &a, ll b){if(a<b) a = b;}

ll pre[MAXN];
int cnt1[1<<6];

int main(){
	freopen("1.in","r",stdin);
	freopen("11.out","w",stdout);
	Read(n); Read(m); Read(k); Read(S);
	a[1] = _a;
	for(int i=1; i<=m; i++){
		id[i] = i;
		for(int j=1; j<=k; j++) Read(a[i][j]);
		if(i<m) a[i+1] = a[i]+k;
	}
	sort(id+1,id+m+1,cmp);
	for(int i=0; i<S; i++) Read(lim[i]);
	sort(lim,lim+S); S = unique(lim,lim+S)-lim;
	for(int i=0; i<S; i++) n -= lim[i];
    n = min(n,(m-S)*k);
	if(n%k) lim[S] = n%k, S++;
	
	int num = n/k, tp = 1<<S;
	memset(f,0xcf,sizeof f);
	f[0][0] = 0;
    for(int i=0; i<tp; i++) cnt1[i] = cnt1[i>>1]+(i&1);
    for(int i=1; i<=m; i++){
        for(int s=tp-1; ~s; s--) if(f[i-1][s]>=0){
            for(int j=0; j<S; j++) if(~s>>j&1)
                upd(f[i][s|(1<<j)],f[i-1][s]+val(i,lim[j]));
            int dlt=0;
            if(i-cnt1[s]<=num) dlt = val(i,k);
            upd(f[i][s],f[i-1][s]+dlt);
        }
    }
	cout<<f[m][tp-1]<<'\n';
	return 0;
}
posted @ 2021-06-30 15:31  oisdoaiu  阅读(22)  评论(0编辑  收藏  举报