POJ3311 Hie with the Pie 状压DP

来源:互联网 发布:淘宝店铺不装修可以吗 编辑:程序博客网 时间:2024/09/21 06:38

今天好不容易切了两道这样的题目,第一道就不提了,完全是题目有特殊情况没判,基本上是入门型的了,这道还不错的,而且有个博客写的特别的好,

http://www.tuicool.com/articles/aUnAru

转一下他的状态方程:

记dp(v, S)为从v点出发,遍历S集合中的每一个点后,回到出发点(0点)的最短距离。递推表达式的推导如下:

如果 S 为空集,即没有需要遍历的结点了。此时可以直接从v点回到0点,则dp(v,S)=sp[v][0] //sp[v][0] 是v点到0点的最短路径距离

如果 S 不为空集,则 dp(v,S)=min{ sp[v][u] + dp(v,S-{u}) }//sp[v][u] 是v点到u点的最短路径距离


这个状态方程描述的就很好了,就算自己没推出来,看了这个也还有自己去想的空间,化抽象为具体嘛,哈哈!!


int n;int mp[10 + 5][10 + 5];int dis[10 + 5][10 + 5];int dp[1<<10][10 + 5];void init() {memset(mp,0,sizeof(mp));memset(dis,0,sizeof(dis));}bool input() {while(scanf("%d",&n),n) {for(int i=0;i<=n;i++)for(int j=0;j<=n;j++) {scanf("%d",&mp[i][j]);dis[i][j] = mp[i][j];}return false;}return true;}void folyd() {for ( int i = 0; i <= n; ++i ) {for ( int j = 0; j <= n; ++j ) {for ( int k = 0; k <= n; ++k ) {if ( dis[i][k] + dis[k][j] < dis[i][j] ) dis[i][j] = dis[i][k] + dis[k][j];}}}}void cal() {folyd();for(int i=1;i<=((1<<n ) - 1);i++) {for(int j=1;j<=n;j++) {if(i == (1<<(j - 1)))dp[i][j] = dis[0][j];//只经过城市jelse {if(i&(1<<(j - 1))) {dp[i][j] = inf;for(int k=1;k<=n;k++) //枚举不以j为最终目标的其它状态,点可以重复走过if(k != j && i&(1<<(k - 1)))dp[i][j] = min(dp[i][j],dp[i^(1<<(j - 1))/*祛除i,j中有相同状态的部分*/][k] + dis[k][j]);}}}}int ans = inf;for(int i=1;i<=n;i++)ans = min(ans,dp[(1<<n) - 1][i] + dis[i][0]);cout<<ans<<endl;}void output() {}int main () {while(true) {init();if(input())return 0;cal();output();}}





0 0
原创粉丝点击