[BZOJ3717]-[PA2014]Pakowanie-状压DP
来源:互联网 发布:网络维保服务公司 编辑:程序博客网 时间:2024/06/03 19:26
说在前面
比较好奇这个「PA」到底是什么比赛…
题目
BZOJ3717传送门
题面
你N个物品和M个包。物品有重量,且不可被分割;包也有各自的容量。要把所有物品装入包中,至少需要几个包?
输入输出格式
输入格式:
第一行两个整数
第二行有n个整数
第三行有m个整数
输出格式:
如果能够装下,输出一个整数表示最少使用包的数目。若不能全部装下,则输出NIE。
解法
第一眼先看数据规模,发现数据范围再大一点就是立方/四次方算法,再小一点就是状压。回头看一看时限,90秒,嗯稳稳的状压。
而且可以发现的是,肯定是先用容量大的包,再用容量较小的包。因此,最多也只会用到N个包(一个物品一个包),不然就无解了。
(然后me就没有思路了)
看了题解,定义两个数组dp[state]和left[state],表示已经装包的物品状态为state时,已经用了dp[state]个包,且最后一个包剩余容量为left[state]
使用填表法,每个state都可以从state^(1<< i )转移过来,转移的时候判断:
- 原来剩余的容量是否够装第i个物品
- 够装,如果满足以下两个条件之一,则更新当前答案
- 原来所用包的个数小于当前最优解
- 原来所用包的个数等于当前最优解,且原来的在装第i个物品之后剩余容量大于当前最优解
- 不够装,如果满足以下两个条件之一,则更新当前答案
- 原来所用包个数+1小于当前最优解
- 原来所用包个数+1等于当前最优解,且开一个新的包装第i个物品的剩余容量大于当前最优解
- 够装,如果满足以下两个条件之一,则更新当前答案
注意这一坨转移条件,必须要按照物品来判断,而不能是仅仅「记录下可以转移到当前状态的那些 包的最小值(相同的时候保留容量最大值)」这样,因为这样记录的是相对最优,但是真正的最优解是要在装物品之后再考虑。
下面是自带大常数的代码
/************************************************************** Problem: 3717 User: Izumihanako Language: C++ Result: Accepted Time:29872 ms Memory:197428 kb****************************************************************/#include <cstdio>#include <cstring>#include <algorithm>using namespace std ;int N , M , a[16777218] , c[105] ;int dp[16777218] , left[16777218] ;bool cmp( const int &A , const int &B ){ return A > B ;}void solve(){ int Fstate = ( 1 << N ) - 1 ; register int i ; for( i = 1 ; i <= Fstate ; i ++ ){ int tmp = i ; int id , maxl = 0 , minc = 0x3f3f3f3f ; dp[i] = 0x3f3f3f3f ; while( tmp ){ int lb = ( tmp&-tmp ) , x = i - lb ; if( a[lb] <= left[x] && ( dp[x] < dp[i] || ( dp[x] == dp[i] && left[x] - a[lb] > left[i] ) ) ) dp[i] = dp[x] , left[i] = left[x] - a[lb] ; else if( ( dp[x] + 1 < dp[i] || ( dp[x] + 1 == dp[i] && c[ dp[x]+1 ] > left[i] + a[lb] ) ) && c[ dp[x]+1 ] >= a[lb] ) dp[i] = dp[x] + 1 , left[i] = c[ dp[x]+1 ] - a[lb] ; tmp -= lb ; } } if( dp[Fstate] == 0x3f3f3f3f ) puts( "NIE" ) ; else printf( "%d" , dp[Fstate] ) ;}int main(){ scanf( "%d" , &N ) ; scanf( "%d" , &M ) ; for( int i = 1 ; i <= N ; i ++ ) scanf( "%d" , &a[i] ) ; for( int i = N ; i ; i -- ) a[1<<(i-1)] = a[i] ; for( int i = 1 ; i <= M ; i ++ ) scanf( "%d" , &c[i] ) ; sort( c + 1 , c + M + 1 , cmp ) ; solve() ;}
阅读全文
0 0
- [BZOJ3717]-[PA2014]Pakowanie-状压DP
- bzoj3717 [PA2014]Pakowanie(状压DP)
- 【PA2014】【BZOJ3717】Pakowanie
- BZOJ3717 [PA2014]Pakowanie
- BZOJ3717: [PA2014]Pakowanie
- 3717: [PA2014]Pakowanie
- 【BZOJ】【P3721】【PA2014 Final】【Bazarek】【题解】【DP】
- BZOJ 3727 PA2014 Final Zadanie 树形DP
- 3727: PA2014 Final Zadanie|树形DP
- 3722: PA2014 Final Budowa|树形DP
- BZOJ 3727 PA2014 树DP 解题报告
- 【PA2014】Fiolki
- bzoj3709 [PA2014]Bohater
- bzoj3713 [PA2014]Iloczyn
- bzoj3715 [PA2014]Lustra
- 3709: [PA2014]Bohater
- 【BZOJ 3714】 [PA2014]Kuglarz
- [PA2014]Fiolki 解题报告
- kotlin的基础语法
- 微服务构建:Spring Boot
- MyBatis完全使用指南
- Linux cpuidle framework(4)_menu governor
- 搭建Easy UI开发环境
- [BZOJ3717]-[PA2014]Pakowanie-状压DP
- FAQ(8):org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: ja
- Linux cpuidle framework(3)_ARM64 generic CPU idle driver
- 免费教材丨第52期:人工智能(复杂问题求解的结构和策略)、人工智能哲学
- 干货丨除了深度学习,你还应该了解这些发展方向
- 重磅丨工信部印发《促进新一代人工智能产业发展三年行动计划 (2018-2020年)》
- Centos7 开机启动Tomcat服务
- bzoj 5088: HDU 6000 Wash
- 熔断器 Hystrix 源码解析 —— 命令执行(三)之执行超时