sgu262:Symbol Recognition(状压DP)
2015-06-11 18:45
330 查看
题目大意:
~~~~~~给出kk个n∗mn*m的0101矩阵SiS_i,求出一个11尽量少的n∗mn*m的0101矩阵PP,满足kk个矩阵与该矩阵的交互不相同,也就是说通过该矩阵能表示出给出的kk个矩阵。
分析:
~~~~~~这题有几个状压DPDP的思路,这里讲一个吧。
~~~~~~假设我们将SiS_i与PP的交定义为QiQ_i,其编号为TiT_i,那么初始的时候交都为空,即T1=T2=...=Tk=0,Q1=Q2=...=Qk=∅T_1=T_2=...=T_k=0,Q_1=Q_2=...=Q_k=\varnothing 。
~~~~~~枚举PP当前的格子(x,y)(x,y),假设有Si,x,y=Sj,x,y=1S_{i,x,y}=S_{j,x,y}=1,且Qi=QjQ_i=Q_j,那么当前格子放11的话,新的QiQ_i依旧等于QjQ_j,反之不等于。所以可以用最小表示搞出该格子放11后的TT。然而TT就是整个状压DPDP的状态。当max{Ti}=k−1max\{T_i\}=k-1的时候,证明所有的TiT_i均不相同,也就是所有的QiQ_i均不相同,此时的PP即为所求。
AC code:
~~~~~~给出kk个n∗mn*m的0101矩阵SiS_i,求出一个11尽量少的n∗mn*m的0101矩阵PP,满足kk个矩阵与该矩阵的交互不相同,也就是说通过该矩阵能表示出给出的kk个矩阵。
分析:
~~~~~~这题有几个状压DPDP的思路,这里讲一个吧。
~~~~~~假设我们将SiS_i与PP的交定义为QiQ_i,其编号为TiT_i,那么初始的时候交都为空,即T1=T2=...=Tk=0,Q1=Q2=...=Qk=∅T_1=T_2=...=T_k=0,Q_1=Q_2=...=Q_k=\varnothing 。
~~~~~~枚举PP当前的格子(x,y)(x,y),假设有Si,x,y=Sj,x,y=1S_{i,x,y}=S_{j,x,y}=1,且Qi=QjQ_i=Q_j,那么当前格子放11的话,新的QiQ_i依旧等于QjQ_j,反之不等于。所以可以用最小表示搞出该格子放11后的TT。然而TT就是整个状压DPDP的状态。当max{Ti}=k−1max\{T_i\}=k-1的时候,证明所有的TiT_i均不相同,也就是所有的QiQ_i均不相同,此时的PP即为所求。
AC code:
[code]#include <cstdio> #include <cstring> #include <map> #define pii pair<int,int> #define mp make_pair using 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; }
相关文章推荐
- From Image-level to Pixel-level Labeling with Convolutional Networks理解
- 黑马程序员--指针(1)
- php中ksort和krsort排序问题
- Android 网络通信框架Volley简介(Google IO 2013)
- Android UI 优化——使用HierarchyViewer工具
- 错误集-objc-class-ref in AppDelegate.o之解决方案
- 银行
- hibernate批量更新和删除数据
- leetcode--Validate Binary Search Tree
- Objective-C开发编码规范
- Android圆形图片--自定义控件
- Objective-C开发编码规范
- iOS 监听键盘弹出的高度,避免挡住界面
- FNV Hash算法
- 请不要使用File#deleteOnExit()
- C#初探-抽学号软件
- Android利用Volley异步加载数据(JSON和图片)完整示例
- CollectionVeiwCell和UICollectionView的手工创建
- 读书笔记——《软件工程》第10~12章
- Hadoop项目实战-用户行为分析之分析与设计