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
", ans==INF?-1:ans);
}
练习2 luogu P2157 学校食堂
大意: n个同学排队去打饭, 第$i$个同学所需的菜口味$a_i$, 最多容忍排在他后面$b_i$个人先打饭, 食堂每做一道菜用时为 $a wedge b$, a为上道菜的口味, b为当前做的菜的口味, 第一道菜不用时间, 求食堂做完所有菜的最短用时