1. 程式人生 > >bzoj4145 [AMPPZ2014]The Prices

bzoj4145 [AMPPZ2014]The Prices

狀壓 etc AI inpu def 現在 while set 一行

Description

你要購買 \(m\) 種物品各一件,一共有 \(n\) 家商店,你到第 \(i\) 家商店的路費為 \(d[i]\) ,在第 \(i\) 家商店購買第 \(j\) 種物品的費用為 \(c[i][j]\) ,求最小總費用。

Input

第一行包含兩個正整數 \(n,m(1\le n\le 100,1\le m\le 16)\) ,表示商店數和物品數。

接下來 \(n\) 行,每行第一個正整數 \(d[i] (1<=d[i]<=1000000)\) 表示到第 \(i\) 家商店的路費,接下來 \(m\) 個正整數,依次表示 \(c[i] [j] (1\le c [i] [j]\le 1000000)\)

Output

一個正整數,即最小總費用。

Sample

Sample Input

3 4
5 7 3 7 9
2 1 20 3 2
8 1 20 1 1

Sample Output

16

Solution

狀壓 \(\mathrm{dp}\)

\(f[i][j]\) 表示現在在第 \(i\) 家店,購買狀態為 \(j\) 的最小費用。

轉移有
\[ f[i][j] = f[i - 1][j]+d[i] \]

\[ f[i][j | (1<<k-1)]=max\{ f[i][j]+cost[i][k] \} \]

\[ f[i][j]=min(f[i][j],f[i-1][j]) \]

#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = a; i <= b; i++)
inline int read() {
    int x = 0, flag = 1; char ch = getchar(); while (!isdigit(ch)) { if (!(ch ^ '-')) flag = -1; ch = getchar(); }
    while (isdigit(ch)) x = (x << 1) + (x << 3
) + ch - '0', ch = getchar(); return x * flag; } int n, m, c[101][17], d[101], f[101][1 << 17]; #define Min(a, b) a = min(a, b) int main() { n = read(); m = read(); int S = (1 << m) - 1; rep(i, 1, n) { d[i] = read(); rep(j, 1, m) c[i][j] = read(); } memset(f, 127, sizeof f); f[0][0] = 0; rep(i, 1, n) { rep(j, 0, S) f[i][j] = f[i - 1][j] + d[i]; rep(k, 1, m) rep(j, 0, S) if (!(j & (1 << k - 1))) Min(f[i][j | (1 << k - 1)], f[i][j] + c[i][k]); rep(j, 0, S) Min(f[i][j], f[i - 1][j]); } printf("%d", f[n][S]); return 0; }

bzoj4145 [AMPPZ2014]The Prices