码迷,mamicode.com
首页 > 其他好文 > 详细

JZYZOJ 1388 旅游 状压dp

时间:2017-11-05 13:13:59      阅读:150      评论:0      收藏:0      [点我收藏+]

标签:href   cstring   pen   多少   asp   scanf   +=   blank   space   

http://172.20.6.3/Problem_Show.asp?id=1388

 
求拓扑排序方案数 状压dp,最开始以为是拓扑排序加数论或者搜索,没想到是状压dp,突然气死.jpg;
完全没有想到状态转移的方法,syq大佬太神了orz;
 
写的时候太沉迷与topsort对人顺序的分组类似于斯特林数求方案数(后来发现不是),忘了最原始的满足条件(事件a在事件b前完成)即可增加方案数的简单dp……(惭愧)
 
所以正解就是按dp进行顺序向状态里加人,对人实现排序,显然如果必须在a前的人都加到队列里了(我这里用的是a后,嗯因为写的时候是直接看syq大佬的代码,其实我觉得记录a前的更符合逻辑)那么a就可以放到这个队列后面了。
 
据此,f[i]表示状态i(i上为1的位表示这一位的人放到队列里了)有多少种方案,a[x]表示x需要哪些人在前面(我写的用的是后面,毕竟从后往前和从前往后并没有什么区别…)。
 
第一次交爆了long long,果然long long是1A率的拦路虎,努力克服
代码
技术分享
 1 #include<iostream>  
 2 #include<cstdio>  
 3 #include<cstring>  
 4 #include<algorithm>  
 5 #include<cmath>
 6 #include<queue>
 7 using namespace std;
 8 const int maxn=30;
 9 int n,m;
10 int a[maxn]={};
11 long long f[(1<<17)+10]={};
12 int main(){
13     scanf("%d%d",&n,&m);int x,y;
14     for(int i=1;i<=m;i++){
15         scanf("%d%d",&x,&y);
16         a[x]|=(1<<(y-1));
17     }
18     int ma=1<<n;f[0]=1;
19     for(int i=1;i<ma;i++){
20         for(int j=0;j<n;j++){
21             if((1<<j)&i){
22                 y=i-(1<<j);
23                 if((a[j+1]&(~y))==0){
24                     f[i]+=f[y];
25                 }
26             }
27         }
28     }
29     printf("%I64d\n",f[ma-1]);
30     return 0;
31 }
View Code

 

JZYZOJ 1388 旅游 状压dp

标签:href   cstring   pen   多少   asp   scanf   +=   blank   space   

原文地址:http://www.cnblogs.com/137shoebills/p/7787032.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!