Gym 100917M Matrix, The(状压dp)

Posted 吃花椒的妙酱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gym 100917M Matrix, The(状压dp)相关的知识,希望对你有一定的参考价值。

  题目大意:给n,a,b,q。一个n行n列矩阵,当且仅当每行有[a,b]个1且每列有一段连续的1才是合法的,q次询问,问第t字典序大的矩阵的样子,a,b,n<=10,t<=1e18,q<=1000
  思路:牛逼题,像数位dp的思路。画张图理解一下。

上图,s表示每行的状态,当si->sj的转移是合法的时候我们才向下面连边(上图默认都是合法的了),可以发现很多状态都是重复的,和数位dp一样的思路——记忆化搜索。
  我们用dp[r][state][mask]表示第r行状态为state,mask表示从1~r行每列是否出现过1的方案数。求来后,对于询问第t个,我们只要每层按照字典序搜过去就解决了。
  接下来看转移方程,发现“每列一段连续1这个条件不好处理”,所以我们引入mask参数,表示1~r行的每列是否出现过1,可以发现不合法的情况是,

如何,下一行出现1,本行有0,之前出现过了1,这样就好判断相邻两行间转移了。
dp[r][state][mask] -> dp[r+1][next_state][next_state | mask]。
牛逼题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ios ios::sync_with_stdio(false),cin.tie(0) 
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define _rep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define pii pair<int ,int >
#define pb(v) push_back(v)
#define all(v) v.begin(),v.end()
#define int long long
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define endl "\\n"
#define fi first
#define se second
#define ls p<<1
#define rs p<<1|1
#define lson p<<1,l,mid
#define rson p<<1|1,mid+1,r
#define AC return 0
const int N=1e5+10;
const int mod=1e9+7;
const double eps=1e-8;
int n,a,b,q;
int ans[11];
int f[11][1<<10][1<<10];
std::vector<int> V;//合法状态
//mask 表示到r行,每列是否出现过1
int dfs1(int r,int sta ,int mask)
    int &temp = f[r][sta][mask];
    if( temp>-1 ) return temp;
    if( r==n )
         return temp = mask==((1<<n)-1);//每列至少一个1
    
    temp = 0;
    for(int nxt:V)
        //不合法的情况就是有
        //1
        //0,,中间可能有若干0
        //1这种情况
        if( mask&(~sta)&nxt) continue;
        temp += dfs1(r+1,nxt,nxt|mask);
    
    return temp;

bool dfs2(int k,int r,int sta,int mask)
    if( r==n ) return true; 
    for(int nxt:V)
        if( mask&(~sta)&nxt) continue;
        if( k <= f[r+1][nxt][nxt|mask] ) 
            ans[r+1] = nxt;
            return dfs2(k,r+1,nxt,nxt|mask);
        
        else k -= f[r+1][nxt][nxt|mask];
    
    return false;

signed main()
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif  
    IOS;
    mst(f,-1);
    cin>>n>>a>>b>>q;
    for(int i=1 ;i<(1<<n) ;i++)
        int cnt=0;
        for(int j=0 ;j<n ;j++) cnt += i>>j&1;
        if( a<=cnt && cnt<=b ) V.push_back(i);
    
    dfs1(0,0,0);
    while( q-- )
        int x;cin>>x;
        if( dfs2(x,0,0,0) )
            _for(i,1,n) 
                for(int j=n-1 ;j>=0 ;j--) cout<<(ans[i]>>j&1);
                cout<<endl;
            
            cout<<endl;
        
        else 
            cout<<"No such matrix."<<endl;
        
    
    AC;

以上是关于Gym 100917M Matrix, The(状压dp)的主要内容,如果未能解决你的问题,请参考以下文章

Gym 101194L / UVALive 7908 - World Cup - [三进制状压暴力枚举][2016 EC-Final Problem L]

Codeforces Gym101341I:Matrix God(随机化构造矩阵降维)***

gym101964 G.Matrix Queries(思维+线段树)

gym101964G Matrix Queries seerc2018g题 数学归纳法+线段树(递归)

bzoj 1002 [FJOI2007]轮状病毒 Matrix-Tree定理+递推

Gym 100917F Find the Length