bzoj4145: [AMPPZ2014]The Prices(狀態壓縮+Dp)

Hanks_o發表於2018-03-22

題目傳送門

解法:
怎麼我跟網上的題解都一樣只想到了n*3^m的演算法。
居然還可以這樣啊。
m<=16那麼可以狀壓為二進位制。
1表示選了0表示沒選

f[i][j]表示前i個商店選j狀態的最小花費。
首先所有f[i][j]=f[i-1][j]+d[i]。
因為他來到了這個商店。
然後對於每一個狀態j。
列舉他每個沒有1的位置 。然後狀態轉移就很容易啦。
當求完所有的狀態。這個商店也不一定一定要買東西。
那麼f[i][j]=min(f[i][j],f[i-1][j])

程式碼實現:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
int f[110][71000],n,m,c[110][21],d[110],bin[21];
int main() {
    scanf("%d%d",&n,&m);
    bin[0]=1;for(int i=1;i<=m;i++)bin[i]=bin[i-1]*2;
    for(int i=1;i<=n;i++) {
        scanf("%d",&d[i]);for(int j=0;j<m;j++)scanf("%d",&c[i][j]);
    }memset(f,63,sizeof(f));f[0][0]=0;
    for(int i=1;i<=n;i++) {
        for(int j=0;j<bin[m];j++)f[i][j]=f[i-1][j]+d[i];
        for(int j=0;j<bin[m];j++)for(int k=0;k<m;k++)if((j&bin[k])==0)
            f[i][j^bin[k]]=min(f[i][j^bin[k]],f[i][j]+c[i][k]);
        for(int j=0;j<bin[m];j++) f[i][j]=min(f[i][j],f[i-1][j]);
    }printf("%d\n",f[n][bin[m]-1]);
    return 0;
}

相關文章