POJ 2288 Islands and Bridges(状态压缩)

举报
Linux猿 发表于 2021/08/05 00:05:47 2021/08/05
【摘要】 题目链接~~> 做题感悟:这题虽然看似很简单其实如果细心的话也不难,但是wa 了 n 次,wa 在了统计最优解个数上,开始没有开数组然后最后统计达到目标状态最优解的个数,这样是不对的,因为你只记录了最终的状态,可能在形成最优解的过程中有许多方法构成了最优解。 解题思路:             &nbsp...

题目链接~~>

做题感悟:这题虽然看似很简单其实如果细心的话也不难,但是wa 了 n 次,wa 在了统计最优解个数上,开始没有开数组然后最后统计达到目标状态最优解的个数,这样是不对的,因为你只记录了最终的状态,可能在形成最优解的过程中有许多方法构成了最优解。

解题思路:

                (1) 、这题很容易想到状态方程 : dp[ S ^ (1<<k) ] [ j ] [ k ] = max(dp[ S ^ (1<<k) ] [ j ] [ k ]  , dp[ S ] [ i ] [ j ]  +  Wk ) ;     dp[ S ^ (1<<k) ] [ j ] [ k ]  代表达到状态S ^ (1<<k) 并以 j , k 结尾的路径最优解 ;

                (2)、还要有记录路径的数组,因为有可能一种状态有许多方法构成 ,注意用 long long or __int64 ;

                (3)、注意只有一个点的情况。

代码:


  
  1. #include<iostream>
  2. #include<ctime>
  3. #include<fstream>
  4. #include<sstream>
  5. #include<stack>
  6. #include<cstring>
  7. #include<map>
  8. #include<vector>
  9. #include<cstdio>
  10. #include<algorithm>
  11. #define INT __int64
  12. using namespace std ;
  13. const int INF = 9999999 ;
  14. const INT MY = 10 + 10 ;
  15. const INT MX = (1<<13) + 10 ;
  16. INT n ,m ;
  17. INT dp[MX][MY][MY] ,v[MY] ,w[MY][MY] ,num[MX][MY][MY] ;
  18. void DP()
  19. {
  20. for(INT S = 0 ;S < (1<<n) ;S++)
  21. for(INT i = 0 ;i < n ;i++)
  22. for(INT j = 0 ;j < n ;j++)
  23. if(dp[S][i][j] != -1)
  24. {
  25. for(INT k = 0 ;k < n ;k++)
  26. {
  27. if(k == i || k == j || S & (1<<k) || !w[j][k]) continue ;
  28. INT mx = v[k] + v[j]*v[k] + dp[S][i][j] ;
  29. if(w[i][k]) mx += v[i]*v[j]*v[k] ;
  30. INT& best = dp[S^(1<<k)][j][k] ;
  31. if(best < mx)
  32. {
  33. best = mx ;
  34. num[S^(1<<k)][j][k] = num[S][i][j] ;
  35. }
  36. else if(best == mx)
  37. num[S^(1<<k)][j][k] += num[S][i][j] ;
  38. }
  39. }
  40. INT sum = 0 ,ans = -1 ;
  41. for(INT i = 0 ;i < n ;i++)
  42. for(INT j = 0 ;j < n ;j++)
  43. {
  44. if(dp[(1<<n)-1][i][j] == -1) continue ;
  45. if(dp[(1<<n)-1][i][j] > ans)
  46. {
  47. ans = dp[(1<<n)-1][i][j] ;
  48. sum = num[(1<<n)-1][i][j] ;
  49. }
  50. else if(dp[(1<<n)-1][i][j] == ans)
  51. sum += num[(1<<n)-1][i][j] ;
  52. }
  53. if(sum)
  54. cout<<ans<<" "<<sum/2<<endl ;
  55. else cout<<"0 0"<<endl ;
  56. }
  57. int main()
  58. {
  59. INT Tx ;
  60. scanf("%I64d",&Tx) ;
  61. while(Tx--)
  62. {
  63. scanf("%I64d%I64d",&n,&m) ;
  64. for(INT i = 0 ;i < n ;i++)
  65. scanf("%I64d",&v[i]) ;
  66. memset(w ,0 ,sizeof(w)) ;
  67. memset(dp ,-1 ,sizeof(dp)) ;
  68. memset(num ,0 ,sizeof(num)) ;
  69. for(INT i = 0 ;i < m ;i++)
  70. {
  71. INT x ,y ;
  72. scanf("%I64d%I64d",&x ,&y) ;
  73. x-- ; y-- ;
  74. w[x][y] = w[y][x] = 1 ;
  75. INT S = (1<<x) + (1<<y) ;//初始化两个点
  76. dp[S][x][y] = dp[S][y][x] = v[x] + v[y] + v[x]*v[y] ;
  77. num[S][x][y] = 1 ;
  78. num[S][y][x] = 1 ;
  79. }
  80. if(n == 1) //特殊处理
  81. {
  82. cout<<v[0]<<" "<<1<<endl ;
  83. continue ;
  84. }
  85. DP() ;
  86. }
  87. return 0 ;
  88. }



文章来源: blog.csdn.net,作者:Linux猿,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/nyist_zxp/article/details/38454067

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。