sgu262:Symbol Recognition(状压DP)

来源:互联网 发布:会员积分软件免费版 编辑:程序博客网 时间:2024/06/05 04:46

题目大意:
      给出knm01矩阵Si,求出一个1尽量少的nm01矩阵P,满足k个矩阵与该矩阵的交互不相同,也就是说通过该矩阵能表示出给出的k个矩阵。

分析:
      这题有几个状压DP的思路,这里讲一个吧。
      假设我们将SiP的交定义为Qi,其编号为Ti,那么初始的时候交都为空,即T1=T2=...=Tk=0Q1=Q2=...=Qk=
      枚举P当前的格子(x,y),假设有Si,x,y=Sj,x,y=1,且Qi=Qj,那么当前格子放1的话,新的Qi依旧等于Qj,反之不等于。所以可以用最小表示搞出该格子放1后的T。然而T就是整个状压DP的状态。当max{Ti}=k1的时候,证明所有的Ti均不相同,也就是所有的Qi均不相同,此时的P即为所求。

AC code:

#include <cstdio>#include <cstring>#include <map>#define pii pair<int,int>#define mp make_pairusing namespace std;const int MAXK = 7;const int MAXN = 11;const int MAXS = 46660;const int INF = 0x3f;int n, m, k, s;int g[MAXK][MAXN][MAXN];int col[MAXN][MAXN];int f[MAXS], fr[MAXS], fx[MAXS], fy[MAXS];map<pii, int> S;int ans[MAXN][MAXN];void upd(int s, int x, int y){    int ts = s, add = f[s], tot = 0, ns = 0;    pii sta[MAXK];S.clear();    for(int i = 0, j = 1; i < k; ++i, ts /= k, j *= k)    {        sta[i] = mp(ts%k, g[i][x][y]);        if(!S.count(sta[i])) S[sta[i]] = tot++;        ns += S[sta[i]]*j;    }    if(f[ns] > add+1)    {        f[ns] = add+1, fr[ns] = s;        fx[ns] = x, fy[ns] = y;    }}int main(){    #ifndef ONLINE_JUDGE    freopen("input.txt", "r", stdin);    freopen("output.txt", "w", stdout);    #endif    scanf("%d%d%d", &n, &m, &k);    for(int i = 0; i < k; ++i)        for(int p = 0; p < n; ++p)            for(int q = 0; q < m; ++q)            {                scanf("%1d", &g[i][p][q]);                col[p][q] |= g[i][p][q];                }    s = 1;    for(int i = 0; i < k; ++i) s *= k;    memset(f, INF, sizeof f);    f[0] = 0;    for(int i = 0; i < n; ++i)        for(int j = 0; j < m; ++j)            if(col[i][j])                for(int p = 0; p < s; ++p)                    if(f[p] < INF)                        upd(p, i, j);    int end = 0;    for(int i = k-1; i >= 0; --i)        end = end*k+i;    printf("%d\n", f[end]);    int now = end;    while(now)    {        ans[fx[now]][fy[now]] = 1;        now = fr[now];    }       for(int i = 0; i < n; ++i)    {        for(int j = 0; j < m; ++j)            printf("%d", ans[i][j]);        puts("");       }    #ifndef ONLINE_JUDGE    fclose(stdin);    fclose(stdout);    #endif      return 0;}
0 0