zoukankan      html  css  js  c++  java
  • JZYZOJ 1388 旅游 状压dp

    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
    ",f[ma-1]);
    30     return 0;
    31 }
    View Code
  • 相关阅读:
    Android开发之日历控件实现
    聚集索引和非聚集索引(整理)
    Android调用WebService(转)
    Android Design
    Android应用的自动升级、更新模块的实现
    Row_Number() OVER 的用法
    WITH AS短语,也叫做子查询部分(subquery factoring)
    创建安卓项目图解
    Android权限设置android.permission
    类型初始值设定项引发异常
  • 原文地址:https://www.cnblogs.com/137shoebills/p/7787032.html
Copyright © 2011-2022 走看看