[POJ 2923] Relocation (动态规划 状态压缩)
2014-10-20 17:26
330 查看
题目链接:http://poj.org/problem?id=2923
题目的大概意思是,有两辆车a和b,a车的最大承重为A,b车的最大承重为B。有n个家具需要从一个地方搬运到另一个地方,两辆车同时开,问最少需要搬运几次?
我先想的是我由A车开始搬,搬运能装的最大的家具总重,然后状态压缩记录下搬运了哪些,然后再由B车搬运,状态压缩记录搬运了哪些。以此类推,直到状态满了。
以上方法TLE
然后,实在想不出来了,看了题解:/article/2391669.html
也就是说先确定哪些状态是两辆车一次可以搬完的。
怎么确定呢?首先我们先确定出给定状态集合中所有可能出现的并且可以被a车运送的重量,然后看是否存在总重量减去可被a车运送的重量所得到的剩余重量是否能够被b车运送。
如果可以,则这个状态是可以被a,b两辆车一次就送完的。
那么怎么确定给定状态集合中所有可能出现的并且可以被a车运送的重量呢?
这又是一个dp。
设计状态dp[i][j]表示状态集合中的前i个物品是否能够组成j这个重量
如果dp[i-1][j-w[i]]已经出现了(就是说如果存在了重量j-w[i],我只需要填上重量w[i]就可以形成j),那么dp[i-1][j]就可以组成。
这个问题结束。
对于总问题:
设计状态dp[i][j]表示从前i种已知可以一次搬完的里面搬状态j需要的最少次数。
状态转移:dp[i][j|mask[i]] = min(dp[i-1][j]+1,dp[i-1][j|mask[i]])
代码
题目的大概意思是,有两辆车a和b,a车的最大承重为A,b车的最大承重为B。有n个家具需要从一个地方搬运到另一个地方,两辆车同时开,问最少需要搬运几次?
我先想的是我由A车开始搬,搬运能装的最大的家具总重,然后状态压缩记录下搬运了哪些,然后再由B车搬运,状态压缩记录搬运了哪些。以此类推,直到状态满了。
以上方法TLE
然后,实在想不出来了,看了题解:/article/2391669.html
也就是说先确定哪些状态是两辆车一次可以搬完的。
怎么确定呢?首先我们先确定出给定状态集合中所有可能出现的并且可以被a车运送的重量,然后看是否存在总重量减去可被a车运送的重量所得到的剩余重量是否能够被b车运送。
如果可以,则这个状态是可以被a,b两辆车一次就送完的。
那么怎么确定给定状态集合中所有可能出现的并且可以被a车运送的重量呢?
这又是一个dp。
设计状态dp[i][j]表示状态集合中的前i个物品是否能够组成j这个重量
如果dp[i-1][j-w[i]]已经出现了(就是说如果存在了重量j-w[i],我只需要填上重量w[i]就可以形成j),那么dp[i-1][j]就可以组成。
这个问题结束。
对于总问题:
设计状态dp[i][j]表示从前i种已知可以一次搬完的里面搬状态j需要的最少次数。
状态转移:dp[i][j|mask[i]] = min(dp[i-1][j]+1,dp[i-1][j|mask[i]])
#include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <map> #include <iterator> #include <vector> using namespace std; typedef long long LL; int T; int n,c[2]; int w[22]; int mask[2222]; int dp[2222]; bool C(int x){ bool can[110]; memset(can,0,sizeof(can)); can[0] = true; int sum = 0; for( int i=1;i<=n;i++ )if((x>>(i-1))&1){ sum += w[i]; for( int j=c[0];j>=w[i];j--){ if( can[j-w[i]] ) can[j] = true; } } for(int i=0;i<=c[0];i++){ if( can[i]&&sum-i<=c[1] ) return true; } return false; } int main(){ scanf("%d",&T); for(int t=1;t<=T;t++){ scanf("%d%d%d",&n,&c[0],&c[1]); for(int i=1;i<=n;i++) scanf("%d",&w[i]); int ptr = 0; for(int i=1;i<(1<<n);i++){ if( C(i) ) mask[++ptr] = i; } const int INF = 9999; fill(dp,dp+2222,INF); dp[0] = 0; for(int i=1;i<=ptr;i++){ for(int j=(1<<n)-1;j>=0;j--) if((mask[i]&j)==0) { dp[mask[i]|j] = min(dp[mask[i]|j],dp[j]+1); } } printf("Scenario #%d:\n%d\n\n",t,dp[(1<<n)-1]); } return 0; }
代码
相关文章推荐
- poj 2923 Relocation(状态压缩+01背包)
- POJ 2923 Relocation 状态压缩DP + 0-1背包
- POJ 2923 Relocation(01背包变形, 状态压缩DP)
- POJ - 2923 Relocation(BFS+状态压缩)
- POJ 2923 Relocation ★(状态压缩+01背包)
- poj 1038 Bugs Integrated, Inc.(动态规划状态压缩)
- POJ 2923 Relocation 状态压缩DP + 0-1背包
- POJ 2923 Relocation(01背包+状态压缩)
- POJ 2923 Relocation(状态压缩+01背包)
- POJ 2923 Relocation (状态压缩 0-1背包)
- POJ 2923 Relocation ★(状态压缩+01背包)
- POJ3254 Corn Fields 状态压缩动态规划,状压动规
- POJ 2923 Relocation(状态压缩+ 01背包)
- Poj-1185 & Nyoj-81 炮兵阵地 (状态压缩动态规划经典题
- poj 2923 Relocation(状态压缩加上01背包)
- poj 2923 Relocation(状态压缩+01背包)
- poj 2923 Relocation 状态压缩01背包
- POJ 2923 Relocation (状态压缩,01背包)
- poj 2923 Relocation(状态压缩+01背包)
- poj 2923 Relocation(状态压缩dp+背包)