NOIP 2017 Day2 题2:宝藏 状态压缩
2017-12-19 17:12
344 查看
NOIP 2017 Day2 题2:宝藏 状态压缩
两篇文章写的很好。
摘自: http://blog.csdn.net/qq_38678604/article/details/78572860 写的真好!!
http://blog.csdn.net/PhantomAgony/article/details/78702573
首先,很容易发现打通后的道路一定是一棵树,并且,若以起点为根并令其深度为0,则题目中的 K 即为这条路所连向的点的深度。
观察数据范围,n≤12,显然是状压dp:
dp状态:dp[i][S] 表示考虑到树的第i层,前i层已选的点的集合为S(二进制状压)的最小代价。
dp方程(刷表法):
已知dp[i][S]时,可枚举所有由不在S中的点构成的集合作为第i+1层,则状态转移为
dp[i][S]→dp[i+1][S|S′]+(i+1)×Σ min{G[a][b]|a∈S,b∈S′,S∩S′=∅}
简单一点,就是 dp[i][S]→dp[i+1][S|S′]+(i+1)×sval[S′][S]}
其中sval[A][B]表示集合A到集合B的最短距离,即集合A中所有点到集合B的最短距离之和。可以先预处理出每个点到每个集合的最短距离pval[i][S](也就是点i到集合S中所有点的距离的最小值),然后用pval[i][B]更新sval[A][B]。
dp顺序:由dp方程可得:从小到大枚举层数,再枚举集合即可
边界条件:枚举根节点,设为root,则dp[0][1<<(root−1)]=0
若S是U的子集,则S关于U的补集:S∧U
判断点k是否在集合S中(即S的第k−1位是否为1):
枚举S的子集:
通过了17组数据,还有三个数据未通过。 待检查
两篇文章写的很好。
摘自: http://blog.csdn.net/qq_38678604/article/details/78572860 写的真好!!
http://blog.csdn.net/PhantomAgony/article/details/78702573
解题思路
首先,很容易发现打通后的道路一定是一棵树,并且,若以起点为根并令其深度为0,则题目中的 K 即为这条路所连向的点的深度。观察数据范围,n≤12,显然是状压dp:
dp状态:dp[i][S] 表示考虑到树的第i层,前i层已选的点的集合为S(二进制状压)的最小代价。
dp方程(刷表法):
已知dp[i][S]时,可枚举所有由不在S中的点构成的集合作为第i+1层,则状态转移为
dp[i][S]→dp[i+1][S|S′]+(i+1)×Σ min{G[a][b]|a∈S,b∈S′,S∩S′=∅}
简单一点,就是 dp[i][S]→dp[i+1][S|S′]+(i+1)×sval[S′][S]}
其中sval[A][B]表示集合A到集合B的最短距离,即集合A中所有点到集合B的最短距离之和。可以先预处理出每个点到每个集合的最短距离pval[i][S](也就是点i到集合S中所有点的距离的最小值),然后用pval[i][B]更新sval[A][B]。
dp顺序:由dp方程可得:从小到大枚举层数,再枚举集合即可
边界条件:枚举根节点,设为root,则dp[0][1<<(root−1)]=0
状压相关技巧
若S是U的子集,则S关于U的补集:S∧U判断点k是否在集合S中(即S的第k−1位是否为1):
S & (1 << (k-1)) != 0 ? "Yes" : "No";
枚举S的子集:
for(int i = S; i; i = (i - 1) & S){...}
通过了17组数据,还有三个数据未通过。 待检查
/* 4 5 1 2 1 1 3 3 1 4 1 2 3 4 3 4 1 */ #include <bits/stdc++.h> //#define debug using namespace std; const int MAX_N =12; const int INF=100000; int G[MAX_N][MAX_N]; int N,M; int dp[12][1<<12]; int pval[12][1<<12]; int sval[1<<12][1<<12]; int U; int ans = INT_MAX; void init(int root){ for(int i = 0; i < N; i++) for(int s = 0; s <= U; s++) dp[i][s] = INF; dp[0][1<<root] = 0; } void pre(){ for(int i=0; i<N; i++){ for(int s=0; s<=U; s++){ for(int k=0; k<N; k++){ if( (s>>k) & 1 ) { // cout << pval[i][s] <<endl; //cout << G[i][k]<<endl; pval[i][s] = min( pval[i][s] , G[i][k] ); } } #ifdef debug cout << i << " "<< bitset<10>(s) << " "<< pval[i][s] <<endl; #endif } } for(int s1=0;s1<=U;s1++){ int C= (s1 ^ U); for(int s2=C; s2>0; s2=(s2-1)&C){ int temp=0; for(int i=0;i<N;i++){ if( s2>>i & 1) { //若果在s2中 temp += pval[i][s1]; } } sval[s2][s1] = ((temp>=INF)?INF:temp); #ifdef debug cout << bitset<10>(s2) << " "<< bitset<10>(s1) << " "<< sval[s2][s1] <<endl; #endif } } } int donggui(){ int ans=1e9; for(int root=0;root<N;root++){ init(root); for(int i=0;i<N;i++){ //i是层次 for(int s1=0; s1<=U ;s1++){ if( dp[i][s1]!=INF){ int C=s1^U; for(int s2=C;s2>0;s2=(s2-1)&C){ dp[i+1][ s1|s2 ] = min( dp[i+1][s1|s2], dp[i][s1] + (i+1)*sval[s2][s1]);//不是sval[s1][s2] } } } } #ifdef debug cout << "root:" << root << endl; for(int i=0;i<=N;i++){ for(int s=0;s<=U; s++){ cout << i << " " << bitset<10>(s) << " "; cout << dp[i][s] << " " <<endl; } cout <<endl ; } #endif for(int i=0;i<N;i++) ans=min( ans ,dp[i][U]); } return(ans); } int main(){ cin >>N >> M; U = (1<<N)-1; for(int i = 0; i <N; i++) //initialize g[i][j] for(int j = 0; j <N; j++) if(i == j) G[i][j] = 0; else G[i][j] = INF; for(int i = 0; i <N; i++) for(int s = 0; s <= U; s++) pval[i][s] = INF; /* for(int i = 0; i <N; i++){ for(int s = 0; s <= U; s++) cout << pval[i][s] <<" "; cout << endl; }*/ for(int s1 = 0; s1 <= U; s1++) for(int s2 = 0; s2 <= U; s2++) sval[s1][s2] = INF; while(M--){ int a,b,v; cin>>a>>b>>v; G[a-1][b-1] = min( G[a-1][b-1] , v ); G[b-1][a-1] = min( G[b-1][a-1] , v ); } #ifdef debug for(int i = 0; i <N; i++) { //initialize g[i][j] for(int j = 0; j <N; j++) cout<<G[i][j]<<" " ; cout << endl; } #endif pre(); cout << donggui(); return 0; }
相关文章推荐
- 【NOIP2017】宝藏(状态压缩,动态规划)
- 【NOIP2017】宝藏(状态压缩,动态规划)
- NOIP2017 Day2 T2 宝藏(状压DP)
- [NOIp2017 Day2 T2] 宝藏treasure (状压dp)
- UOJ 265 NOIP 2016 DAY2 T3 浅谈预处理状态压缩动态规划
- NOIP2017 提高Day2-2 宝藏 解题报告
- [NOIP2017]宝藏
- NOIP2017提高组D2T2[宝藏]
- NOIP 2017 Day2 总结
- 【NOIP2017】Day2
- luogu3959【noip2017】宝藏(状压dp)
- NOIP2017 - 宝藏
- 【jzoj4908】【NOIP2016提高组】【愤怒的小鸟】【状态压缩动态规划】
- 递推专题 - 两种状态互推问题:经典问题 打砖块 + NOIP2015 Day2 T2
- LOJ #2290(「THUWC 2017」随机二分图-状态压缩dp)
- 2017 NOIP 提高组模拟赛(四)Day2(计蒜客)
- 【jzoj3737】【挖宝藏】【斯坦纳树】【状态压缩动态规划】
- 洛谷P3959 [NOIP2017]宝藏
- jzoj5408 【NOIP2017提高A组集训10.21】Dark (巧设状态的DP)
- NOIP 2017 Day2 题解?