题目连接:hdu_5555_Immortality of Frog

题意:

给你一个NxN的网格,第N行的每一列都有个青蛙,这些青蛙只会往上走,上帝会在每个膜中放一个长生不老的药,一共有N个膜,每个膜覆盖一些区间,如果这个区间恰好为N那么就是好膜,否则是坏膜,每个青蛙最多只能穿过10个坏膜,问全部青蛙吃到药,并全部到顶层的分配方案。

题解:

1.我们首先统计每一列有多少个坏膜,其中一列如果大于10,那么青蛙肯定不能全部到达顶部,ans=0;

2.假设青蛙把全部的坏膜吃完了,当前的方案数为p,好膜是都可以吃的,那么此时的答案就是好膜的个数的阶乘*p。

3.这时我们就该来算全部吃完坏膜的方案数了。

4.首先每一列最多只有10个坏膜,那么我们可以用状态压缩来保存每一列坏膜的状态,但这个状态只是这一列的相对位置,比如这一列第10行的坏膜的相对位置为1,第24行的坏膜相对位置为2

5.我们dp[i][j]表示第i列的坏膜相对位置的吃掉情况,那么我们要转移到i+1列,就要转移第i列已经吃过的坏膜的情况到第i+1列,因为j表示的是当前列的坏膜相对位置,我们要对应找到i+1列的坏膜的相对位置,列如:第i列有 第12,15,18,20是坏膜,第i+1列有第15,20,30,40是坏膜,假设第i列的第15行坏膜已经吃掉,第15行在第i列的相对位置为2,此时我们要转移到i+1列上,对应的就是第i+1列的15行,第15行在i+1列的相对位置为1,这样就是dp[i][1<<(2-1)]转移到了dp[i+1][1<<(1-1)]。

6.到最后我们取的是最后一列的全部坏膜吃掉的情况,这里就包含了所有坏膜吃完的情况,然后乘上好膜的阶乘即可


 #include<cstdio>
#include<vector>
#define F(i,a,b) for(int i=a;i<=b;i++)
typedef long long LL;
using namespace std; const int N=,mod=;
int dp[N][N],n,l[N],r[N],good,jie[N],p1[],p2[];
vector<int>g[N]; void init(){
jie[]=;
F(i,,)jie[i]=(LL)jie[i-]*i%mod;
} void del(int x){
F(i,,(int)g[x].size()-){
p1[i]=-;
F(j,,(int)g[x+].size()-)
if(g[x][i]==g[x+][j]){p1[i]=j;break;}
}
F(i,,(int)g[x+].size()-){
p2[i]=-;
F(j,,(int)g[x].size()-)
if(g[x+][i]==g[x][j]){p2[i]=j;break;}
}
} inline int new_s(int x,int y){
int ans=;
F(i,,(int)g[x].size()-){
if(p1[i]==-){if(!((y>>i)&))return -;}
else if(y>>i&)ans|=(<<p1[i]);
}//这个坏膜在当前列的编号对应下一列的编号
return ans;
} inline void up(int &x,int y){x+=y,x=x>mod?x-mod:x;} int main(){
init();
int t;scanf("%d",&t);
F(ic,,t){
scanf("%d",&n),good=;
F(i,,n)scanf("%d",l+i),g[i].clear();
F(i,,n)scanf("%d",r+i);
F(i,,n)if(l[i]==&&r[i]==n)good++;
else F(j,l[i],r[i])g[j].push_back(i);
int flag=,ans=;//坏膜大于10,无法分配
F(i,,n)if(g[i].size()>){flag=;break;}
if(!flag){
F(i,,n){//dp初始化
int sz=g[i].size();
F(j,,(<<sz))dp[i][j]=;
}
dp[][]=;
F(i,,n-){
del(i);
F(j,,(<<(int)g[i].size())-){
int now=new_s(i,j);
if(now!=-){//将上一列已经吃过的坏膜转移到这列对应的状态
up(dp[i+][now],dp[i][j]);
F(k,,(int)g[i+].size()-)//如果上一列没有这个坏膜或者有但没吃,那么这一列肯定吃掉这个膜
if(p2[k]==-||!(now>>k&))
up(dp[i+][now|(<<k)],dp[i][j]);
}
}
}
ans=(LL)jie[good]*dp[n][(<<(int)g[n].size())-]%mod;
}
printf("Case #%d: %d\n",ic,ans);
}
return ;
}

hdu_5555_Immortality of Frog(状压DP)的更多相关文章

  1. 【状压DP】【CF8C】 Looking for Order

    传送门 Description 给你n个点,每次可以从起点到最多两个点然后回到起点.求经过每个点最少一次的最短欧氏距离和是多少 Input 第一行是起点的坐标 第二行是点的个数\(n\) 下面\(n\ ...

  2. 【状压DP】【UVA11795】 Mega Man's Mission

    传送门 Description 你要杀n个怪,每杀掉一个怪那个怪会掉落一种武器,这种武器可以杀死特定的怪.游戏初始你有一把武器,能杀死一些怪物.每次只能杀一只,求有多少种杀怪方法. Input 多组数 ...

  3. P3959 宝藏 状压dp

    之前写了一份此题关于模拟退火的方法,现在来补充一下状压dp的方法. 其实直接在dfs中状压比较好想,而且实现也很简单,但是网上有人说这种方法是错的...并不知道哪错了,但是就不写了,找了一个正解. 正 ...

  4. BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]

    1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3336  Solved: 1936[Submit][ ...

  5. nefu1109 游戏争霸赛(状压dp)

    题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109 //我们校赛的一个题,状压dp,还在的人用1表示,被淘汰 ...

  6. poj3311 TSP经典状压dp(Traveling Saleman Problem)

    题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...

  7. [NOIP2016]愤怒的小鸟 D2 T3 状压DP

    [NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可 ...

  8. 【BZOJ2073】[POI2004]PRZ 状压DP

    [BZOJ2073][POI2004]PRZ Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍 ...

  9. bzoj3380: [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一(spfa+状压DP)

    数据最多14个有宝藏的地方,所以可以想到用状压dp 可以先预处理出每个i到j的路径中最小权值的最大值dis[i][j] 本来想用Floyd写,无奈太弱调不出来..后来改用spfa 然后进行dp,这基本 ...

随机推荐

  1. C++ 类的继承、虚拟继承、隐藏、占用空间

    主函数: #include <iostream> #include "test.h" #include "testfuc.h" using name ...

  2. 安装cocoapods遇到的一些问题

    其实可以直接到https://github.com/CocoaPods/Specs上把所需的文件夹下载下来 解压后命名为master放在本地的 ~/.cocoapods/repos  下面就行 但是使 ...

  3. windows service and process 的关系

    1.查询windows 对应的服务 sc query > 1.txt notepad 1.txt 2.查询对应的进程信息 tasklist /m > tasks.txt notepad t ...

  4. treecnt

    treecnt  ﹡    LH (命题人)   基准时间限制:1 秒 空间限制:131072 KB 分值: 40 给定一棵n个节点的树,从1到n标号.选择k个点,你需要选择一些边使得这k个点通过选择 ...

  5. 【原创】mdk5宏定义的使用小结

    前几天在网上申请了一块芯片为stm32f103cbt6的小板子. 在用keil编程的过程中发现一些小问题,总结如下: 使用mdk5开发,与之前的库函数的引用方式已经改变.不需要在选项的c/c++标签页 ...

  6. ==、equals、hashCode区别?

    [==.equals().hashCode()区别?] 1)== 运算符用来比较两个变量的值是否相等. 即该运算符用于比较变量对应得内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是 ...

  7. Vasya and String(尺取法)

    Vasya and String time limit per test 1 second memory limit per test 256 megabytes input standard inp ...

  8. Python 正则表达式学习笔记

    本文介绍了Python对于正则表达式的支持,包括正则表达式基础以及Python正则表达式标准库的完整介绍及使用示例.本文的内容不包括如何编写高效的正则表达式.如何优化正则表达式,这些主题请查看其他教程 ...

  9. 深入理解JNI(《深入理解android》(author : 邓凡平)读书札记)

    JNI的技术特点: java能够调用native代码. native代码能够调用java代码.   JNI的技术考虑: 实现java代码的平台无关型. java语言发展初期使用C和C++代码,避免重复 ...

  10. nefu 449 超级楼梯 &&nefu 911 跨楼梯

    nefu 449 超级楼梯 Description 有一楼梯共M级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第M级,共有多少种走法? Input 输入数据首先包含一个整数N,表示测试实例的 ...