[AMPPZ2014]The Prices
阿新 • • 發佈:2018-09-16
cstring class 依次 sam 套路 out ice cpp 當前
Description
你要購買m種物品各一件,一共有n家商店,你到第i家商店的路費為d[i],在第i家商店購買第j種物品的費用為c[i][j],求最小總費用。
Input
第一行包含兩個正整數n,m(1<=n<=100,1<=m<=16),表示商店數和物品數。
接下來n行,每行第一個正整數di表示到第i家商店的路費,接下來m個正整數,
依次表示c[i][j](1<=c[i][j]<=1000000)。
Output
一個正整數,即最小總費用。
Sample Input
3 4
5 7 3 7 9
2 1 20 3 2
8 1 20 1 1
Sample Output
16
狀壓dp做多了發現都是套路題。。。設f[i][sta]表示當前在第i個商店,買的物品狀態為sta的花費。轉移分兩種:
- \(f[i][sta]=f[i-1][sta]+d[i]\),這個表示不買東西,從之前的商店過來
- \(f[i][sta]=f[i][sta^(1<<(j-1))]+v[i][j],(sta\&(1<<(j-1))==1)\),這個表示在當前商店裏買了東西
註意一點,從之前的商店不一定是從第i-1個商店轉移過來,因此我們在最後要令\(g[i][sta]=min{\sum\limits_{j=1}^i f[j][sta]}\),由於\(g[i][sta]只\)在第一個轉移被用到,而且第二個轉移只是\(f[i][]\)的內部轉移,因此我們直接用f代替g也是可以的
/*program from Wolfycz*/ #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define inf 0x7f7f7f7f using namespace std; typedef long long ll; typedef unsigned int ui; typedef unsigned long long ull; inline int read(){ int x=0,f=1;char ch=getchar(); for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1; for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+ch-'0'; return x*f; } inline void print(int x){ if (x>=10) print(x/10); putchar(x%10+'0'); } const int N=1e2,M=16; int d[N+10],val[N+10][M+10]; int f[N+10][(1<<M)+10]; int main(){ int n=read(),m=read(); for (int i=1;i<=n;i++){ d[i]=read(); for (int j=1;j<=m;j++) val[i][j]=read(); } memset(f,63,sizeof(f)); f[0][0]=0; for (int i=1;i<=n;i++){ for (int sta=0;sta<1<<m;sta++){ for (int j=1;j<=m;j++) if (sta&(1<<(j-1))) f[i][sta]=min(f[i][sta],f[i][sta^(1<<(j-1))]+val[i][j]); f[i][sta]=min(f[i][sta],f[i-1][sta]+d[i]); } for (int sta=0;sta<1<<m;sta++) f[i][sta]=min(f[i][sta],f[i-1][sta]); } printf("%d\n",f[n][(1<<m)-1]); return 0; }
[AMPPZ2014]The Prices