POJ2923--Relocation(01背包+状压dp)

果然对状压DP,我根本就不懂=。=

/**************************************************
Problem: 2923		User: G_lory
Memory: 720K		Time: 157MS
Language: G++		Result: Accepted
**************************************************/
#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

const int MAXN = 1 << 11;
const int INF = 0x5f5f5f5f;

int n, c1, c2;
int w[12];
int dp[MAXN];
int vis[MAXN];
int bag[MAXN];

bool ok(int st)
{
    memset(vis, 0, sizeof vis);
    vis[0] = 1;
    int sum = 0;
    for (int i = 0; i < n; ++i)
    {
        if ((1 << i) & st)//if (i & n)
        {
            sum += w[i];
            if (sum > c1 + c2) return false;// 很好理解,如果比两个车装的物体和还大,不可能一次装完
            for (int j = c1; j >= w[i]; --j)
            {
                if (vis[j - w[i]])  // 对n这个状态含有的物体做01背包,
                    vis[j] = 1;     // vis[j]=1表示物体可以刚好组成j,且j可以c1被装下
            }
        }
    }

    for (int i = 0; i <= c1; ++i)   // 就是看sum能否被两车一次装下
        if (sum - i <= c2 && vis[i]) return true;
    return false;
}

int main()
{
    int t;
    scanf("%d", &t);
    for (int cas = 1; cas <= t; ++cas)
    {
        scanf("%d%d%d", &n, &c1, &c2);

        for (int i = 0; i < n; ++i)
        {
            scanf("%d", &w[i]);
        }

        int st = (1 << n) - 1;
        int cnt = 0;

        for (int i = 1; i <= st; ++i)
        {
            if (ok(i))
            {
                bag[cnt++] = i;
            }
        }

        for (int i = 1; i <= st; ++i) dp[i] = INF;
        dp[0] = 0;

        for (int i = 0; i < cnt; ++i)
        {
            for (int j = st; j >= 0; --j)
            {
                if (dp[j] != INF && (j & bag[i]) == 0)
                {
                    dp[j | bag[i]] = min(dp[j | bag[i]], dp[j] + 1);
                }
            }
        }

        printf("Scenario #%d:\n%d\n\n", cas, dp[st]);

    }
    return 0;
}

  

时间: 2024-11-04 11:01:37

POJ2923--Relocation(01背包+状压dp)的相关文章

Relocation POJ - 2923(01背包+状压dp)

Relocation POJ - 2923 原文地址:https://www.cnblogs.com/megadeth/p/11361007.html

【弱校胡策】2016.4.14 (bzoj2164)最短路+状压DP+矩阵乘法+高斯消元+树链剖分+线段树+背包DP

cyyz&qhyz&lwyz&gryz弱校胡策 命题人:cyyz ws_fqk T3暴力写挫了 50+10+0滚粗辣! 奇妙的约会(appointment.cpp/c/pas) [问题描述] DQS和sxb在网上结识后成为了非常好的朋友,并且都有着惊人 的OI水平.在NOI2333的比赛中,两人均拿到了金牌,并保送进入 HU/PKU.于是两人决定在这喜大普奔的时刻进行面基. NOI2333参赛选手众多,所以安排了n个考点,DQS在1号考点, 而sxb在n号考点.由于是举办全国性赛事

HDU 6149 Valley Numer II(状压DP)

题目链接 HDU6149 百度之星复赛的题目……比赛的时候并没有做出来. 由于低点只有15个,所以我们可以考虑状压DP. 利用01背包的思想,依次考虑每个低点,然后枚举每个状态. 在每个状态里面任意枚举不在这个状态中的两个点,如果能构成一个valley,那么更新答案. #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i,

【UVa】Headmaster&#39;s Headache(状压dp)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1758 晕....状压没考虑循环方向然后错了好久.. 这点要注意...(其实就是01背包变成了完全背包QAQ 我们将课程拆成两个点,然后状压 那么答案就是(1<<(s<<1))-1 转移就不说了,,,,,太简单.. #include <cstdio> #in

【一天一DP计划】状压DP

##P1896 互不侵犯[状压dp] 用01串表示每一行的可行解 列与列之间的限制条件在转移的时候continue x&=(-x)可以找到x的二进制位上有多少个1 关于位运算的优先级!不确定就无脑加括号哦哦 reference: https://www.luogu.org/blog/virus2017/1896dnqec Date: 2019.10.04 */ #include<bits/stdc++.h> using namespace std; #define int long l

旅行商问题 状压DP

旅行商问题描述 现在有一个旅行商,在一个国家做生意.这个国家有N(2 <= N <= 15)个城市,城市之间有单行道可以通行,每条路都有相应的路费(0 <= d(I,j) <= 1000).现在旅行商要从0号城市出发,经过所有的城市,最后回到0号城市.要求所花的路费最小.保证这些道路能构成一个环(可以一笔画). 问题简化 给出一张带权有向有环图,用邻接矩阵表示,d(i,j)表示ij两个节点之间边的权值,INF表示没有边.要求从0号节点出发,经过每一个节点后正好回到0号节点,问经过边

状压dp入门

(先处理好基本的位运算的东西) 为了更好的理解状压dp,首先介绍位运算相关的知识. 1.'&'符号,x&y,会将两个十进制数在二进制下进行与运算,然后返回其十进制下的值.例如3(11)&2(10)=2(10). 2.'|'符号,x|y,会将两个十进制数在二进制下进行或运算,然后返回其十进制下的值.例如3(11)|2(10)=3(11). 3.'^'符号,x^y,会将两个十进制数在二进制下进行异或运算,然后返回其十进制下的值.例如3(11)^2(10)=1(01). 4.'<&

HDU 1074 Doing Homework (状压dp)

题意:给你N(<=15)个作业,每个作业有最晚提交时间与需要做的时间,每次只能做一个作业,每个作业超出最晚提交时间一天扣一分 求出扣的最小分数,并输出做作业的顺序.如果有多个最小分数一样的话,则按照作业字典序输出(注意:输入也是按照字典序输入的) 题解:首先想到的是暴力dfs,但是会超时.接着我们看到n最大只有15,因此可以使用状压dp,但是状态不能用位置表示 但我们可以这样:0表示此作业没有做过,1表示已经用过了,接着遍历0->(1<<n)-1贪心(例如:3(011)可以找2(0

POJ 3254 Corn Fields (状压DP,轮廓线DP)

题意: 有一个n*m的矩阵(0<n,m<=12),有部分的格子可种草,有部分不可种,问有多少种不同的种草方案(完全不种也可以算1种,对答案取模后输出)? 思路: 明显的状压DP啦,只是怎样压缩状态?跟轮廓线DP一样,按格子为单位来设计状态,一个状态只需要表示到其上方和左方的格子,所以最多只需要保存min(n,m)个01状态就行了(可以尝试旋转一下矩阵),最多需要12位.用哈希表来做会比较快吧,不用去考虑无效的状态,比如出现相邻两个1. 1 //#include <bits/stdc++.