zoukankan      html  css  js  c++  java
  • The Prices(有依赖性的状压dp)(去不同商店买东西先花不同路费)

    The Prices 「BZOJ4145」

    Decscription

    你要购买(m)种物品各一件,一共有(n)家商店,你到第i家商店的路费为(d[i]),在第i家商店购买第j种物品的费用为(c[i][j]),求最小总费用。

    Input

    第一行包含两个正整数(n,m(1<=n<=100,1<=m<=16)),表示商店数和物品数。接下来(n)行,每行第一个正整数(d[i](1<=d[i]<=1000000))表示到第(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

    Solution

    这道题根据(m)的范围我们大概知道是状压dp,具体怎么实现的呢,我们还是要提前将路费加上,注意不能加重,之后类似于依赖背包。
    具体解释看代码吧

    Code

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn=1<<16,Inf=0x3f3f3f3f;
    int n,m,f[105][maxn],a[105][20],d[105];
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i){
    		scanf("%d",&d[i]);
    		for(int j=1;j<=m;++j){
    			scanf("%d",&a[i][j]);
    		}
    	}
    	int maxs=(1<<m)-1;
    	for(int i=0;i<=n;++i){
    		for(int j=0;j<=maxs;++j){
    			f[i][j]=Inf;
    		}
    	}
    	f[0][0]=0;
    	for(int i=1;i<=n;++i){
    		for(int j=0;j<=maxs;++j){//先付路费
    			f[i][j]=f[i-1][j]+d[i];
    		}//初始化完之后,不管j是多少,f[i][j]只有1个i的路费,这样避免不同的状态j加重路费
    		for(int k=1;k<=m;++k){//后买东西
    			for(int j=0;j<=maxs;++j){
    				if(j&(1<<(k-1)))continue;
    				f[i][j|(1<<(k-1))]=min(f[i][j|1<<(k-1)],f[i][j]+a[i][k]);
    			}
    		}
    		for(int j=0;j<=maxs;++j){//决策在哪个商店
    			f[i][j]=min(f[i][j],f[i-1][j]);//可以用本次循环的f[i][j]传递
    		}
    	}
    	printf("%d
    ",f[n][maxs]);
    	return 0;
    }
    
  • 相关阅读:
    sql性能查询
    ASP.Net Web应用程序与EXCEL交互时遇到的权限问题
    Connection strings for Excel 2007
    获取异常的具体出处dbms_utility.format_error_backtrace
    C#获取Excel架构信息的方法
    Oracle强杀进程
    C#游标溢出(访问数据库)解决方案。
    Visual C# 2008 调试技巧一
    【POI】修改Excel内容
    【Eclipse】在Eclipse工具中自定义类注释
  • 原文地址:https://www.cnblogs.com/Lour688/p/13200934.html
Copyright © 2011-2022 走看看