状压背包
不太好说
很容易写
然而一开始写了个 O(n3m) 的T傻了没反应过来……
总之这个就是当前走到了第i个商店,购买状态是s,然后背包转移, O(nm2n) 。
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define For(i,a,b) for(int i=a;i< b;i++)
#define fors(s0,s) for(int s0=s;s0;s0=(s0-1)&s)
#define shl(i) (1 << (i))
inline int rd() {
char c = getchar();
while (!isdigit(c)) c = getchar() ; int x = c - '0';
while (isdigit(c = getchar())) x = x * 10 + c - '0';
return x;
}
inline void upmin(int&a , int b) { if (a > b) a = b ; }
int n , m , d[101] , c[101][16] , all , f[2][65536];
void input() {
n = rd() , m = rd();
For(i , 0 , n) {
d[i] = rd();
For(j , 0 , m) c[i][j] = rd();
}
all = shl(m);
}
void solve() {
int now = 0 , pre = 1;
memset(f , 0x3f , sizeof f);
f[0][0] = 0;
For(i , 0 , n) {
now ^= 1 , pre ^= 1;
For(s , 0 , all) f[now][s] = f[pre][s] + d[i];
For(k , 0 , m) For(s , 0 , all) if (!(s & shl(k)))
upmin(f[now][s | shl(k)] , f[now][s] + c[i][k]);
For(s , 0 , all) upmin(f[now][s] , f[pre][s]);
}
printf("%d\n" , f[now][all - 1]);
}
int main() {
input();
solve();
return 0;
}