太洗脑了;

  题目意思:初始队列是1,2, 3.......n ;在打乱这个队列切保证每个数字都不在原来的位置上的情况下给出一个具有+,- 的队列;

被打乱的队列 和 原来队列 对应位置的大小的关系是那个给定的 +,- 队列;

YY: 炸一看7S,n=20;状压DP 啊 开森的写完了,TTTTTTTT;这不是逗我玩呢么,他有1000组测试样例

还是DP !

  思路:

      每一位的数字有俩中分配方式 填补前面的+ 或者后面的-

      但是我们的DP 一般都是线性的不可能在枚举到一位的时候,左右的状态都被处理好

      所以我们选择一种处理方式

          1:从前往后处理,枚举到的数字往前面的+ 的位置放,或者记录下数字的个数等到枚举位置是- 时往里放

          2:从后往前 和一的刚好相反

      一般会选1 这样更舒服;

      对于要维护的值不难发现有 位置(pos),有多少个+号所在的位置没有确定数字(cnt[+]),剩余没有用到的数字;

对于选1 的要是枚举到的位数是   -   那么一定要找个数字把他填上   所以有下面的解法

  解法1:dp [i] [j] [k]  ::   枚举到位置I  时 ;

                 有J 个+号位置的数字好没有确定;

                      还有K个数字可用;

      所以很容易可以得到 当前位置是+ 的时候

          (1)选择把这个数字放到前面            

              dp[i][j][k]+= dp[i-1][j][k]*j;

          (2)选择吧这个数留下来为了填后面的减号

               dp[i][j][j]+= dp[i-1][j-1][k-1];

      当该位置是-    的时候

          (1)选择把这个数字放到前面,并找个前面剩下数字把这个位置填补

              dp[i][j][k]+= dp[i-1][j+1][k+1]*(j+1)*(k+1);

          (2)选择这个数字留下来,并找个前面的剩下数字把这个位置填补

                dp[i][j][k]+= dp[i-1][j][k]*j;

    至此dp[n-1][0][0]是答案;

代码1

#include <cstdio>
#include <string>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
char tmp[];
int n;
LL dp[][][];
int main()
{
while(~scanf("%s",tmp))
{
n=strlen(tmp);
if(tmp[]!='+' || tmp[n-]!='-')
{
puts("");
continue;
}
memset(dp,,sizeof dp);
dp[][][]=;
for(int i=;i<n;i++)
{
if(tmp[i]=='+')
{
for(int j=;j<=(i+);j++)
{
for(int k=;k<=(i+);k++)
{
if(i>=)
dp[i][j][k]+= dp[i-][j][k]*j;
if(i>=&&j>=&&k>=)
dp[i][j][j]+= dp[i-][j-][k-];
}
}
}
else
{
for(int j=;j<=(i+);j++)
{
for(int k=;k<=(i+);k++)
{
if(i>=)
dp[i][j][k]+= dp[i-][j+][k+]*(j+)*(k+);
if(j>=)
dp[i][j][k]+= dp[i-][j][k]*j;
}
}
}
}
cout<<dp[n-][][]<<endl;
}
return ;
}

优化:

  这个是不需要三个维度的  :

      试想当到达位置P 那么一共有P个数字被决定是

          放到+,-,还是留下了 ,

      对于留下的数字       和   剩下的    没有被分配数值的+号位置的数量

      有着相等的关系 理由如下

              (减号必须被分配)

          对于位置数 有加号和减号

             num[加号]+num[减号]    =   num[被分配的加号]+num[剩下的加号]+num[减号]=P;

          对于数字 有分配和未分配

             num[分配]+num[未分配]=      num[被分配到加号]+num[分配到减号]+num[未分配]=P;

          所以剩下的数字和未分配的加号是相等的

所以可以省一个维度

优化

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <cstring>
#include <cstdlib>
typedef long long LL;
using namespace std;
LL n;
LL dp[][];
char tmp[];
int main()
{
while(scanf("%s",tmp)!=EOF)
{
n=strlen(tmp);
if(tmp[]=='-'||tmp[n-]=='+')
{
puts("");
continue;
}
memset(dp,,sizeof(dp));
dp[][]=;
for(int i=; i<n; i++)
{
if(tmp[i]=='+')
for(int j=; j<=(i+); j++)
{
if(i>=&&j>=)
dp[i][j]+=dp[i-][j-];
if(i>=)
dp[i][j]+=dp[i-][j]*j;
}
else
for(int j=; j<=(i+); j++)
{
if(i>=)
dp[i][j]+=dp[i-][j+]*(j+)*(j+);
if(i>=)
dp[i][j] +=dp[i-][j]*j;
}
}
cout<<dp[n-][]<<endl;
}
return ;
}

HDU-4689 Derangement的更多相关文章

  1. HDOJ 4689 Derangement DP

    DP具体解释见: http://blog.csdn.net/liguan1/article/details/10468139 Derangement Time Limit: 7000/7000 MS ...

  2. HDU-4689 Derangement DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4689 题意:初始序列1,2...n,求所有满足与初始序列规定大小的错排数目.. 这道题目感觉很不错~ ...

  3. TOJ 4689: Sawtooth

    4689: Sawtooth Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByteTotal Submit: 26     ...

  4. HDOJ 2111. Saving HDU 贪心 结构体排序

    Saving HDU Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  5. 【HDU 3037】Saving Beans Lucas定理模板

    http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...

  6. hdu 4859 海岸线 Bestcoder Round 1

    http://acm.hdu.edu.cn/showproblem.php?pid=4859 题目大意: 在一个矩形周围都是海,这个矩形中有陆地,深海和浅海.浅海是可以填成陆地的. 求最多有多少条方格 ...

  7. HDU 4569 Special equations(取模)

    Special equations Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u S ...

  8. HDU 4006The kth great number(K大数 +小顶堆)

    The kth great number Time Limit:1000MS     Memory Limit:65768KB     64bit IO Format:%I64d & %I64 ...

  9. HDU 1796How many integers can you find(容斥原理)

    How many integers can you find Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d ...

  10. hdu 4481 Time travel(高斯求期望)(转)

    (转)http://blog.csdn.net/u013081425/article/details/39240021 http://acm.hdu.edu.cn/showproblem.php?pi ...

随机推荐

  1. LCA 最近公共祖先 tarjan离线 总结 结合3个例题

    在网上找了一些对tarjan算法解释较好的文章 并加入了自己的理解 LCA(Least Common Ancestor),顾名思义,是指在一棵树中,距离两个点最近的两者的公共节点.也就是说,在两个点通 ...

  2. 怎么制作U盘系统/PE启动盘

    原地址:http://jingyan.baidu.com/article/3c48dd3453d05de10be358fb.html 不用光驱就能启动系统,做一个U盘启动系统就搞定,下面我给大家演示如 ...

  3. 2013 吉林通化邀请赛 Play Game 记忆化搜索

    dp[ba][ta][bb][tb]表示a堆牌从下面拿了ba张,从上面拿了ta张.b堆牌从下面拿了bb张,从上面拿了tb张.当前玩家能得到的最大的分数. 扩展方式有4种,ba+1,ta+1,bb+1, ...

  4. PS CC 2014 把一个图层输出为文件的方法

    近期在设计一个Qt控件,须要获得一个圆饼的图片,在用PS绘制后发现保存的时候总是会带着背景,用PNG格式保存之后背景依旧存在.仅仅是变成了透明的.刚才在Google上查到了仅仅保存单一图层而全然没有背 ...

  5. vim在编译器 . 命令(点命令)

    时间:2014.06.28 地点:基地 -------------------------------------------------------------------------------- ...

  6. hdu3622(二分+two-sat)

    传送门:Bomb Game 题意:给n对炸弹可以放置的位置(每个位置为一个二维平面上的点),每次放置炸弹是时只能选择这一对中的其中一个点,每个炸弹爆炸的范围半径都一样,控制爆炸的半径使得所有的爆炸范围 ...

  7. liunx清理磁盘du -h --max-depth=1 /data/*

    liunx清理磁盘du -h --max-depth=1 /data/*

  8. 基于FP-Tree的关联规则FP-Growth推荐算法Java实现

    基于FP-Tree的关联规则FP-Growth推荐算法Java实现 package edu.test.ch8; import java.util.ArrayList; import java.util ...

  9. zoj3471(状压dp)

    题目连接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4257 题意:不超过10种气体,两两之间相互碰撞可以产生一定的能量,如 ...

  10. TypeError: Cannot read property &#39;style&#39; of null 错误解决

    错误信息例如以下: JSP代码例如以下: <c:if test ="${not empty excelErrors}"> <div id="excelE ...