Bzoj 4145: [AMPPZ2014]The Prices

Bzoj 4145: [AMPPZ2014]The Prices

状态压缩dp

\(f[i][j]\)表示前i个商店 , 状态为j的最小花费.

考虑什么东西也不买和买了东西.

买了东西的话,就要到i地.

然后转移:\(f[i][j] = min(f[i][j] , f[i][j ^ (1 << k - 1)] + c[i][k])\)

不买东西

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

/*header*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#define rep(i , x, p) for(int i = x;i <= p;++ i)
#define sep(i , x, p) for(int i = x;i >= p;-- i)
#define gc getchar()
#define pc putchar
#define ll long long
#define mk make_pair
#define fi first
#define se second
using std::min;
using std::max;
using std::swap;

inline int gi() {
    int x = 0,f = 1;char c = gc;
    while(c < '0' || c > '9') {if(c == '-')f = -1;c = gc;}
    while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = gc;}return x * f;
}

void print(int x) {
    if(x < 0) pc('-') , x = -x;
    if(x >= 10) print(x / 10);
    pc(x % 10 + '0');
}

const int maxN = 100 + 7;

void gmin(int &x , int y) {
    x = x > y ? y : x;
}

int f[maxN][65540] , c[maxN][maxN], d[maxN];

int main() {
    int n = gi() , m = gi();
    rep(i , 1, n) {
        d[i] = gi();
        rep(j , 1, m) c[i][j] = gi();
    }
    memset(f , 0x3f, sizeof(f));
    f[0][0] = 0;
    rep(i , 1, n) {
        rep(j , 0, (1 << m) - 1) f[i][j] = f[i - 1][j] + d[i];
        rep(j , 0, (1 << m) - 1) {
            rep(k , 1, m) {
                if(j & (1 << k - 1))
                    f[i][j] = min(f[i][j] , f[i][j ^ (1 << k - 1)] + c[i][k]);
            }
        }
        rep(j , 0, (1 << m) - 1) f[i][j] = min(f[i][j] , f[i - 1][j]);
    }
    printf("%d\n", f[n][(1 << m) - 1]);
    return 0;
}

原文地址:https://www.cnblogs.com/gzygzy/p/10263060.html

时间: 2024-12-12 17:25:24

Bzoj 4145: [AMPPZ2014]The Prices的相关文章

BZOJ 4145: [AMPPZ2014]The Prices( 状压dp + 01背包 )

我自己只能想出O( n*3^m )的做法....肯定会T O( nm*2^m )做法: dp( x, s ) 表示考虑了前 x 个商店, 已买的东西的集合为s. 考虑转移 : 先假设我们到第x个商店去, so初始时 dp( x, s) = dp( x-1, s ) + d[x] 然后我们可以对第x个商店做01背包, dp(x, s + {h} ) = min( dp( x, s + {h} ) , dp( x, s) + c[x][h]) ) ( h ∉ s ). 之后我们再比较到第x个商店划不

BZOJ 4145 [AMPPZ2014] The Prices 解题报告

感觉也是一个小清新题.. 我们考虑设立状态 $Dp[i][s]$ 表示考虑了前 $i$ 个商店后,购买状态为 $s$ 的最小花费. 转移的话就枚举每个商店 $i$,首先令: $$Dp[i][s] = Dp[i - 1][s] + D[i]$$ 这个过程表示到达这个商店. 然后枚举每个状态 $s$,然后枚举每个不在 $s$ 里的物品 $j$,令: $$Dp[i][s + \{j\}] = min(Dp[i][s + \{j\}], Dp[i][s] + Cost[i][j])$$ 这个过程就相当于

BZOJ 4145 AMPPZ2014 The Prices 状压DP

题目大意:给定n个商店和m种物品,你需要每种物品买一个,去第i个商店的路费是di,第i个商店出售第j种物品的价格是ci,j,求最小花销 令fi,j表示当前已经考虑了前i个商店,购买的状态为j的最小花销 然后每个商店内跑个背包即可 时间复杂度O(nm2m) #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int

Bzoj 4143: [AMPPZ2014]The Lawyer

Bzoj 4143: [AMPPZ2014]The Lawyer 抱歉,水了这一片博客..( ~~ 为了凑出AMPPZ2014.... ~~ 显然记录最小的右端点,和最大的左端点即可. /*header*/ #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <cmath> #d

BZOJ 4144: [AMPPZ2014]Petrol

4144: [AMPPZ2014]Petrol Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 457  Solved: 170[Submit][Status][Discuss] Description 给定一个n个点.m条边的带权无向图,其中有s个点是加油站. 每辆车都有一个油量上限b,即每次行走距离不能超过b,但在加油站可以补满. q次询问,每次给出x,y,b,表示出发点是x,终点是y,油量上限为b,且保证x点和y点都是加油站,请回答能否从x走

循环队列+堆优化dijkstra最短路 BZOJ 4152: [AMPPZ2014]The Captain

循环队列基础知识 1.循环队列需要几个参数来确定 循环队列需要2个参数,front和rear 2.循环队列各个参数的含义 (1)队列初始化时,front和rear值都为零: (2)当队列不为空时,front指向队列的第一个元素,rear指向队列最后一个元素的下一个位置: (3)当队列为空时,front与rear的值相等,但不一定为零: 3.循环队列入队的伪算法 (1)把值存在rear所在的位置: (2)rear=(rear+1)%maxsize ,其中maxsize代表数组的长度: 4.循环队列

BZOJ 4143: [AMPPZ2014]The Lawyer( sort )

水题... 排序搞出每天的会议有哪些, 然后再按照会议的开始时间和结束时间排序, 最晚开始的和最早结束的会议不是同一场而且最晚开始的时间>最早结束的会议就有可能方案 ---------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostrea

BZOJ 4152: [AMPPZ2014]The Captain( 最短路 )

先按x排序, 然后只有相邻节点的边才有用, 我们连起来, 再按y排序做相同操作...然后就dijkstra ------------------------------------------------------------------------ #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> #include

bzoj4145 [AMPPZ2014]The Prices 状压 DP

题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4145 题解 好像这道题有不少方法呢. ...谁叫这道题有点简单,所以方法多呗. 我的方法: 求出 \(f[S]\) 表示要在同一家商店购买 \(S\) 中的物品的最小代价. 然后 \(dp[S]\) 表示购买 \(S\) 中的商品的最小代价.枚举子集转移即可. 时间复杂度 \(O(m2^n+3^n)\). 还有一个不错的做法: \(dp[i][S]\) 表示在前 \(i\) 个商店买 \(S