状压训练

1, CF418 Cunning Gena

大意: Gena参加一个比赛, Gena有n个朋友, 比赛有m道题, Gena自己并不会做题, Gena能花费$w_i$元让第$i$个朋友帮忙做出所有他会的题, 但要求Gena有至少$k_i$个显示屏, 一台显示屏$b$元, 求Gena解决所有题的最少花费.

 

比较简单的状压, 按k排序一下再dp就好了, 卡空间要滚动数组

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string.h>
#define REP(i,a,n) for(int i=a;i<=n;++i)
using namespace std;
typedef long long ll;

const int N = 110;
const ll INF = 0x3f3f3f3f3f3f3f3f;
int n, m, b;
struct _ {
	int w, k, v;
} a[N];
ll dp[2][1<<20];

void chkmin(ll &x, ll y) {x=min(x,y);}


int main() {
	scanf("%d%d%d", &n, &m, &b);
	REP(i,1,n) {
		int cnt;
		scanf("%d%d%d", &a[i].w, &a[i].k, &cnt);
		REP(j,1,cnt) {
			int t;
			scanf("%d", &t);
			a[i].v |= 1<<t-1;
		}
	}
	sort(a+1,a+1+n,[](_ a,_ b){return a.k<b.k;});
	memset(dp[0], 0x3f, sizeof dp[0]);
	dp[0][0] = 0;
	ll ans = INF;
	int mx = (1<<m)-1, cur = 0;
	REP(i,1,n) {
		cur ^= 1;
		memcpy(dp[cur], dp[cur^1], sizeof dp[cur]);
		REP(j,0,mx) if (dp[cur^1][j]!=INF) {
			chkmin(dp[cur][j|a[i].v],dp[cur^1][j]+a[i].w);
		}
		REP(j,0,mx) if (dp[cur][j]!=INF) {
			dp[cur][j] += (ll)b*(a[i].k-a[i-1].k);
		}
		ans = min(ans, dp[cur][mx]);
	}
	printf("%lld\n", ans==INF?-1:ans);
}

 

练习2 luogu P2157 学校食堂

大意: n个同学排队去打饭, 第$i$个同学所需的菜口味$a_i$, 最多容忍排在他后面$b_i$个人先打饭, 食堂每做一道菜用时为 $a \wedge b$, a为上道菜的口味, b为当前做的菜的口味, 第一道菜不用时间, 求食堂做完所有菜的最短用时

 

posted @ 2019-02-26 09:29  uid001  阅读(135)  评论(0编辑  收藏  举报