HDU-4689 Derangement
太洗脑了;
题目意思:初始队列是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的更多相关文章
- HDOJ 4689 Derangement DP
DP具体解释见: http://blog.csdn.net/liguan1/article/details/10468139 Derangement Time Limit: 7000/7000 MS ...
- HDU-4689 Derangement DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4689 题意:初始序列1,2...n,求所有满足与初始序列规定大小的错排数目.. 这道题目感觉很不错~ ...
- TOJ 4689: Sawtooth
4689: Sawtooth Time Limit(Common/Java):1000MS/3000MS Memory Limit:65536KByteTotal Submit: 26 ...
- HDOJ 2111. Saving HDU 贪心 结构体排序
Saving HDU Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- 【HDU 3037】Saving Beans Lucas定理模板
http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...
- hdu 4859 海岸线 Bestcoder Round 1
http://acm.hdu.edu.cn/showproblem.php?pid=4859 题目大意: 在一个矩形周围都是海,这个矩形中有陆地,深海和浅海.浅海是可以填成陆地的. 求最多有多少条方格 ...
- HDU 4569 Special equations(取模)
Special equations Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u S ...
- HDU 4006The kth great number(K大数 +小顶堆)
The kth great number Time Limit:1000MS Memory Limit:65768KB 64bit IO Format:%I64d & %I64 ...
- HDU 1796How many integers can you find(容斥原理)
How many integers can you find Time Limit:5000MS Memory Limit:32768KB 64bit IO Format:%I64d ...
- hdu 4481 Time travel(高斯求期望)(转)
(转)http://blog.csdn.net/u013081425/article/details/39240021 http://acm.hdu.edu.cn/showproblem.php?pi ...
随机推荐
- 黑马程序员:Java基础总结----静态代理模式&动态代理
黑马程序员:Java基础总结 静态代理模式&动态代理 ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 静态代理模式 public class Ts { ...
- 2013 吉林通化邀请赛 Play Game 记忆化搜索
dp[ba][ta][bb][tb]表示a堆牌从下面拿了ba张,从上面拿了ta张.b堆牌从下面拿了bb张,从上面拿了tb张.当前玩家能得到的最大的分数. 扩展方式有4种,ba+1,ta+1,bb+1, ...
- python语言学习2——安装python
python是跨平台的,可以,在各种操作系统上安装 window平台下安装python,安装步骤: 下载安装包 下载地址:https://www.python.org/ftp/python/3.5.0 ...
- PowerDesigner中SQL文件、数据库表反向生成PDM
1 反向生成PDM 1) 创建一个空的PDM模型(选择相应的DBMS): 2) 选择[Database]--[Update Model from Database ...
- Selenium之利用Excel实现参数化
Selenium之利用Excel实现参数化 说明:我是通过Workbook方式来读取excel文件的,这次以登陆界面为例 备注:使用Workbook读取excel文件,前提是excel需要2003版本 ...
- loading加载中效果
(function(){ try{ var ui={ loading:{ addCssStyle:function(text) { var head = document.getElementsByT ...
- java中取得上下文路径的方法
1.request.getContextPath(); 获得web根的上下文环境 如 /tree tree是web项目的root context 2.可以在servlet的init方法里 String ...
- php如何判断用户是从指定页面跳转进来的
$_SERVER['HTTP_REFERER']下'HTTP_REFERER' 引导用户代理到当前页的前一页的地址(如果存在).由 user agent 设置决定.并不是所有的用户代理都会设置该项,有 ...
- cocos2d-x 3.1.1 学习笔记[2]Sprite 精灵
Sprite应该是用到最多的一个类吧.无法想像一个游戏没有精灵将怎样进行愉快的玩耍. Sprite继承于Node 和 TextureProtocol. Sprite是一个2d的图像. Sprite能够 ...
- Android中TweenAnimation四种动画切换效果
点击每个按钮都会有对应的动画显示 activity代码: package com.tmacsky; import android.app.Activity; import android.os.Bun ...