转载:http://blog.csdn.net/qian99/article/details/39138329

题意:给出n个物品,每个物品有两种属性Wi,Ti,有q组查询,每组查询要求在n个物品中选出一些,并使得两个属性的和为Mi,Si。

思路:刚开始看感觉是神题,后来仔细想了想,其实本质上就是个背包。最裸着写的话,那么就是dp[i][j][k]表示使用前i个物品,是否可以凑出第一个属性j,第二个属性k,要输出方案的话记录一下路径就可以了。一开始这么写了一发,加了一些乱七八糟的优化,还是会T。虽然这题时限还算宽,但这么写复杂度还是太高了。考虑到第一个属性最多只有50,那么可以用一个二进制数来表示是否能凑出第一个属性的情况,即:第i位为1表示可以凑出i。使用这种方法的好处是对于物品i可以直接算出第一种属性的组合情况,枚举一下新增的位,更新一下结果就行了。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-8
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 400 + 10;
const int M = 51;
short ans[200010][52];
ull f[200010];
int W[maxn],T[maxn];
map<ull,int>mp;
int main()
{
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    for(int i = 1;i <= M + 1;++i)
        mp[1LL<<(i-1LL)] = i;
    int t,n,q;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&q);
        memset(ans,0,sizeof(ans));
        memset(f,0,sizeof(f));
        f[0] = 1;
        ull v,x;
        for(int i = 1;i <= n;++i)
        {
            scanf("%d%d",&W[i],&T[i]);
            for(int j = 200000;j >= T[i];--j)
            {
                v = f[j];                        //f[j]表示第二个属性为j时,能够凑出的第一个属性的集合,用一个二进制数表示,第i位为1表示可以凑出这个数
                f[j] |= (f[j - T[i]]<<W[i]) & ((1LL<<M+1) - 1);          //计算使用当前物品能够得到的新的集合,在集合f[j - T[i]]添加W[i]的物品,
                                                                         //即原来能得到的每个值加上W[i],等价于将其左移W[i]位
                for(ull k = v ^ f[j];k ; k &= k-1)               //枚举新增加的集合
                {
                    x = (k ^ (k - 1)) & k;                      
                    ans[j][mp[x] - 1] = i;                       //将新增的位置更新,记录是使用了哪个物品达到的这个状态
                }
            }
        }
        int m,s,p;
        for(int i = 0;i < q;++i)
        {
            scanf("%d%d",&m,&s);
            if(!ans[s][m])
                puts("No solution!");
            else
            {
                printf("%d",ans[s][m]);
                p = ans[s][m];
                m -= W[p];
                s -= T[p];
                while(m)
                {
                    p = ans[s][m];
                    printf(" %d",p);
                    m -= W[p];
                    s -= T[p];
                }
                puts("");
            }
        }
    }
    return 0;
}

转载于:https://www.cnblogs.com/thefirstfeeling/p/4410611.html

zoj 3812 状压dp相关推荐

  1. Travel(HDU 4284状压dp)

    题意:给n个城市m条路的网图,pp在城市1有一定的钱,想游览这n个城市(包括1),到达一个城市要一定的花费,可以在城市工作赚钱,但前提有工作证(得到有一定的花费),没工作证不能在该城市工作,但可以走, ...

  2. ZOJ 3755 - Mines (状压DP)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5178 题意: 大家都玩过扫雷吧. 给你n*m的扫雷数字.数字都在偶数列上. 也 ...

  3. zoj3802:easy 2048 again(状压dp)

    zoj月赛的题目,非常不错的一个状压dp.. 题目大意是一个一维的2048游戏 只要有相邻的相同就会合并,合并之后会有奖励分数,总共n个,每个都可以取或者不取 问最终得到的最大值 数据范围n<= ...

  4. POJ 1038 Bugs Integrated Inc (复杂的状压DP)

    \(POJ~1038~~*Bugs~Integrated~Inc:\) (复杂的状压DP) \(solution:\) 很纠结的一道题目,写了大半天,就想练练手,结果这手生的.其实根据之前那道炮兵阵地 ...

  5. codeforces 8C. Looking for Order 状压dp

    题目链接 给n个物品的坐标, 和一个包裹的位置, 包裹不能移动. 每次最多可以拿两个物品, 然后将它们放到包里, 求将所有物品放到包里所需走的最小路程. 直接状压dp就好了. #include < ...

  6. UVA10296 Jogging Trails(中国邮递员问题)(欧拉回路、一般图最大权匹配 / 状压DP)

    整理的算法模板合集: ACM模板 目录 思路 UVA10296 Jogging Trails 题目翻译: 给你n个点,m条无向边,每条边有一定的距离数值,构造成一个连通图.问从任意一点出发,遍历所有的 ...

  7. POJ 2411 Mondriaan‘s Dream(最清楚好懂的状压DP讲解)(连通性状态压缩DP)

    poj 2411 Mondriaan's Dream(最清晰的状压DP解析) 闫氏DP大法好 我们这里是一列一列地来,因为是一个棋盘性的状态压缩DP,从哪个方向都一样 摆放的小方格总方案数 等价于 横 ...

  8. 【每日DP】day2、P1879 [USACO06NOV]Corn Fields G玉米地(状压DP模板题)难度⭐⭐⭐★

    昨天的每日DP我还在写01背包,今天就到状压DP了,真刺激. P1879 [USACO06NOV]Corn Fields G 题目链接 输入 2 3 1 1 1 0 1 0 输出 9 一道简单的状压D ...

  9. hdu 4778 Gems Fight! 状压dp

    转自wdd :http://blog.csdn.net/u010535824/article/details/38540835 题目链接:hdu 4778 状压DP 用DP[i]表示从i状态选到结束得 ...

最新文章

  1. LeetCode简单题之数组的度
  2. Python-OpenCV 处理视频(三)(四)(五): 标记运动轨迹 运动检测 运动方向判断
  3. 程序员的10个快乐瞬间!
  4. [深度学习-NLP]什么是Self-attention, Muti-attention和Transformer
  5. MogDB与PostgreSQL分区策略语法测试
  6. 真壕!腾讯员工平均月薪 7 万!
  7. Important Tips
  8. 数据库之间的远程操作
  9. 笔记本怎样做无线打印服务器,自己的笔记本怎么连打印机_笔记本怎样无线连接打印机...
  10. 谷歌浏览器保存网页为PDF
  11. 8年一线.NET开发程序员求职
  12. 12032 解救小哈
  13. Tony.SerialPorts.RS232串口模块(二)
  14. 如何将Chrome设为iPhone和iPad上的默认Web浏览器
  15. ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。
  16. 如何快速设置CorelDRAW中网格
  17. 怎样制定自己的职业规划
  18. fatfs文件系统详解之f_read函数分析
  19. 尚学堂python线上培训多少钱
  20. 第二类换元法三角代换的万能代换

热门文章

  1. python写一个系统-熬了一晚上,小白用Python写了一个股票提醒系统
  2. python解释器的安装步骤-Python本地及虚拟解释器配置过程解析
  3. python画笑脸图案-如何用Python画滑稽笑脸
  4. python画柱状图代码-python plotly画柱状图代码实例
  5. python绘制柱形图-Python openpyxl Excel绘制柱形图
  6. python是中国的吗-操作系统3:编程语言和操作系统是什么关系?
  7. python类型转换-Python中如何进行数据类型转换?
  8. python自动测试p-python自动化测试报告(excel篇)
  9. python使用方法-python中dict使用方法详解
  10. python基础代码事例-学习笔记:python3,代码。小例子习作(2017)