[状压DP][DFS]JZOJ 2679 跨时代

Description

钟逆时针而绕,恶物狰狞的倾巢,我谦卑安静地于城堡下的晚祷,压抑远古流窜的蛮荒暗号,而管风琴键高傲的说,那只是在徒劳。我的乐器在环绕,时代无法淘汰我霸气的皇朝。 你无法预言,因为我越险,翅越艳;没有句点,跨时代蔓延,翼朝天。 月下浮雕,魔鬼的浅笑,狼迎风嚎,蝠翔似黑潮,用孤独去调尊严的色调。我跨越过世代,如兽般的姿态,琴声唤起沉睡的血脉。不需要被崇拜,如兽般的悲哀,只为永恒的乐曲存在,醒过来。 去年万众瞩目的《跨时代》专辑发行之后,周杰伦又开始了他的世界巡回演唱会《超时代》。有人说过:如果你喜欢一个人,那你一定要去看一场他的演唱会;电视机前的1m距离和在演唱会现场哪怕100m的距离,两种感觉都是截然不同的。
       所以小G作为铁杆歌迷,也计划带着小Y去看周杰伦的演唱会。 演唱会当然要圈出一个空地,然后才能布置道具。 演唱会的第一站,公司临时跟当地的消防局借了n个栏杆,打算用这n个栏杆围出一个矩形。而麻烦的是,这些栏杆有长有短,这就给围场地带来了一些难度。 所以公司聘请你来写一个程序,计算用这n个栏杆做多围出面积多大的矩形。
(注:必须要刚好围成一个矩形,即不能出现多余的边长,且不能切断栏杆,但所给栏杆不一定要全部用上)

Input

第一行一个正整数n,表示栏杆的数量。
第二行n个正整数,表示每根栏杆的长度li。

Output

仅一行一个正整数,表示用给出的栏杆围成最大矩形的面积,如果不能围成矩形,输出”No Solution”(不包含引号)。

Sample Input

4
1 1 1 1

Sample Output

1

Data Constraint

Hint

对于30%的数据,1<=n<=10。 对于100%的数据,1<=n<=16,1<=li<=15。

分析

n的大小提示我们使用状压

那么我们设f[i]表示i中的边全部选上后,有无组合能够达到总长度的一半

这个是比较简单的DP过程

然后DFS,记录两根长的和和两根宽的和,以及选边的状态,最后判断能否分成一半即可

#include <iostream>
#include <cstdio>
#include <memory.h>
using namespace std;
int n,mxb,l[16],f[1<<16];
bool b[500];
int cnt,ans;

void Calc(int S,int s) {
    if (s&1) return;
    memset(b,0,sizeof b);b[0]=1;
    for (int i=0;i<n;i++) {
        if (S<(1<<i)) break;
        if (S&(1<<i))
            for (int j=s;j-l[i]+1;j--)
                b[j]|=b[j-l[i]];
    }
    if (b[s>>1]) f[S]=1;
}

void DFS(int dep=0,int sa=0,int sb=0,int a=0,int b=0) {
    if (dep==n) {
        if (f[sa]&&f[sb]) ans=max(ans,a*b>>2);
        return;
    }
    DFS(dep+1,sa,sb,a,b);
    DFS(dep+1,sa|(1<<dep),sb,a+l[dep],b);
    DFS(dep+1,sa,sb|(1<<dep),a,b+l[dep]);
}

int main() {
    scanf("%d",&n);mxb=1<<n;
    for (int i=0;i<n;i++) scanf("%d",&l[i]);
    for (int i=0;i<mxb;i++) {
        cnt=0;
        for (int j=0;j<n;j++) cnt+=l[j]*((i&(1<<j))>0);
        Calc(i,cnt);
    }
    DFS();
    printf((ans?"%d":"No Solution"),ans);
}

原文地址:https://www.cnblogs.com/mastervan/p/11145010.html

时间: 2024-08-29 13:39:19

[状压DP][DFS]JZOJ 2679 跨时代的相关文章

poj2411--Mondriaan&#39;s Dream(状压dp+dfs)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12315   Accepted: 7189 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

【题解】P3959 宝藏 - 状压dp / dfs剪枝

P3959 宝藏 题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的m  条道路和它们的长度. 小明决心亲自前往挖掘所有宝藏屋中的宝藏.但是,每个宝藏屋距离地面都很远, 也就是说,从地面打通一条到某个宝藏屋的道路是很困难的,而开发宝藏屋之间的道路 则相对容易很多. 小明的决心感动了考古挖掘的赞助商,赞助商决定免费赞助他打通一条从地面到某 个宝藏屋的通道,通往哪个宝藏屋则由小明来决定. 在此基础上,小明还需要考虑如何开凿

LA UVaLive 6625 Diagrams &amp; Tableaux (状压DP 或者 DFS暴力)

题意:给一个的格子图,有 n 行单元格,每行有a[i]个格子,要求往格子中填1~m的数字,要求每个数字大于等于左边的数字,大于上边的数字,问有多少种填充方法. 析:感觉像个DP,但是不会啊...就想暴力试试,反正数据量看起来不大才7,但是...TLE了,又换了一个暴力方法,2秒多过了,差点啊. 其实这是一个状压DP,dp[i][s]表示在第 i 列,在集合 s 中有方法数,那么怎么转移呢,这个还是挺简单的,就是判断第i+1列是不是比第 i 列都大于等于就ok了, 输入时先把行,转化成列,再计算,

JZOJ 3747(状压DP)

这题是一道状压DP,暂时还不是很懂. #include<cstdio> #include<cstring> #include<iostream> using namespace std; const int LENM=1010,N=11,M=1e9+7; char s[N]; int n,m,u,ind[200],f[LENM][1<<10],g[N],ans[N],gg[N],num1[1<<10],ff[1<<10][5]; in

ZOJ3305Get Sauce 状压DP,

状压DP的题目留个纪念,首先题意一开始读错了,搞了好久,然后弄好了,觉得DFS可以,最后超时,修改了很久还是超时,没办法看了一下n的范围,然后觉得状压可以,但是没有直接推出来,就记忆化搜索了一下,可是一直错,莫名奇妙,然后没办法看了一下题解,发现了下面这个比较好的方法,然后按照这个方程去推,然后敲,也是WA了好多把,写的太搓了,没人家的清楚明了,唉~也算是给自己留个纪念,状压一直做的都不太好~唉~还好理解了, 参考了  http://blog.csdn.net/nash142857/articl

poj 2411 Mondriaan&#39;s Dream(状压DP)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12232   Accepted: 7142 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

BZOJ 1072 排列 状压DP

题意:链接 方法:状压DP? 题解:这题其实没啥好写的,不算很难,推一推就能搞出来. 首先看到这个问题,对于被d整除这个条件,很容易就想到是取余数为0,所以想到可能状态中刚开始含有取余数. 先说我的第一个想法,f[i][j]表示选取i个数且此时的mod为j,这样的思想是第一下蹦出来的,当时想的就是在线来搞最终的答案.不过转瞬即发现,这TM不就是暴力吗魂淡!并没有什么卵用,于是开始想这个状态可不可以做什么优化. 显然第二维的j并不需要太大的优化,暂且先将其搁置一边,来考虑第一维的i怎么优化. 把滚

UVA 10817 Headmaster&#39;s Headache 状压DP

记录两个状态S1,S2分别记录哪些课程被1个人教过或2个人教过,然后记忆化搜索 UVA - 10817 Headmaster's Headache Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Problem D: Headmaster's Headache Time limit: 2 seconds The headmaster of Spr

POJ 2411 Mondriaan&#39;s Dream(状压DP)

http://poj.org/problem?id=2411 求一个n*m矩阵用1*2方块去填满的情况有几种 思路:状压dp,先预处理那些状态之间能互相到达,情况就几种,上一个两个1,下一个状态也两个1,上一个为0,下一个必须为1,还有一种是上一个为1,下一个为0的情况 然后就一层层往后递推即可 代码: #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; int