POJ 4979 海贼王之伟大航路 【状压dp】【北大ACM/ICPC竞赛训练】

该死的题让我想起来艾斯之死...

首先想到dp(i)代表从1到【i表示的这些岛屿】所花的最小时间,然后每次枚举最后一个岛屿以此缩小范围,但发现枚举了最后一个岛屿后没有办法转移,因为不知道倒数第二个岛屿是什么,随着倒数第二个岛屿的不同,时间的增加也会不同,也就是不具备【无后效性】。

因此想到再加一个参数去约束当前问题的状态,dp(i,j)代表1到【i代表的这些点】所需的最少时间,且这趟旅程的最后一个岛屿是j,这样就可转移了,每次枚举倒数第二岛屿;答案就是dp( (1<<n) -1,n )

具体的位运算来判断i有没有包含k岛屿,自己拿笔推一下就行了

 1 #include<iostream>
 2 #define INF 1000000000
 3 using namespace std;
 4
 5 int a[20][20],n;
 6 int memo[66000][20];
 7
 8 int dp(int i,int j){//dp[i,j]代表1到【i代表的这些点】所需的最少时间,且这趟旅程到的最后一个点在j
 9     if( j==1 && i!=1 ) return memo[i][j] = INF; //只有当旅程只包含1的时候最后一个到的点才能是1
10     if(memo[i][j]!=INF) return memo[i][j];
11     if( i == 1 && j==1 )  return memo[i][j]=0;
12     //枚举倒数第二个岛屿在哪
13     for(int k=1;k<n;k++){
14         if(k==j) continue;//倒数第二个岛不能是倒数第一个岛
15         if( i & 1<<(k-1) ) memo[i][j] = min( memo[i][j], dp(i- (1<<(j-1)),k)+a[k][j] );
16     }
17     return memo[i][j];
18 }
19
20 int main(){
21     for(int i=1;i<66000;i++)
22         for(int j=1;j<20;j++) memo[i][j]=INF;
23
24     cin>>n;
25     for(int i=1;i<=n;i++)
26         for(int j=1;j<=n;j++) cin>>a[i][j];
27
28     //固定起点为1和终点为N
29     cout<<dp( (1<<n)-1,n );
30     return 0;
31 }

原文地址:https://www.cnblogs.com/ZhenghangHu/p/9368618.html

时间: 2024-10-09 13:28:58

POJ 4979 海贼王之伟大航路 【状压dp】【北大ACM/ICPC竞赛训练】的相关文章

源哥每日一题第十三弹 百练4124:海贼王之伟大航路 状压dp

连接:http://bailian.openjudge.cn/practice/4124 题意:从1到n走过所有点恰好一次最短时间.乱搞的话会完美的超时(阶乘级别的复杂度,虽然范围很小,但是也足够超时了). 思路:先想一个不太成熟的思路.用dp[s][j]表示.s记录的是每个点是否被走过的状态.而dp[s][j]表示的是从1走到j状态所用的最小时间.这样的思路成不成立呢?首先,考虑初始值.开始是在1号点,那么dp[1][1]自然就是0了,其他就是max:另外,题面说只要遍历每一个点,而于顺序的话

POJ 6048 泰国佛塔 【dfs搜索】【疯狂剪枝!】【北大ACM/ICPC竞赛训练】

1 #include<iostream> 2 #include<cmath> 3 using namespace std; 4 5 int volumn[25],minArea[25];//volumn[i]为第i层到第1层蛋糕所用最小体积 6 int ans,n,m; //minArea[i]为第i层到第1层蛋糕所用[最小侧面积] 7 int area;//当前dfs状态所需要用的表面积 8 9 int maxV(int level,int r,int h){//用level层蛋

POJ Find the Winning Move【minmax搜索+alpha-beta剪枝】【北大ACM/ICPC竞赛训练】

1 #include<iostream> 2 using namespace std; 3 4 int row,col,chess; 5 char board[5][5]; 6 7 int minSearch(int i,int j,int alpha); 8 int maxSearch(int i,int j,int beta); 9 10 11 bool check(int r,int c){ 12 if( board[r][0]==board[r][1] && board

POJ 8471 切割回文 【dp】【北大ACM/ICPC竞赛训练】

1 #include<iostream> 2 #include<vector> 3 #define INF 100000 4 using namespace std; 5 6 string s; 7 char a[1005]; 8 vector<int> hui[1005];//hui[i]里的k指 k到i组成回文 9 int dp[1005];//dp[i]代表前i个字符要切几刀 10 11 int main(){ 12 int t; cin>>t; 13

POJ 1194 Zipper 【dp】【北大ACM/ICPC竞赛训练】

现在做dp题有点感觉了,以前估计会觉得这题很难,现在觉得这是道不是很水的水题 dp[i][j]代表A里前i个加上B里前j个能不能组成C的前i+j个. 至于怎么想到的呢,n是200,有1000组数据,所以猜测要dp二维,然后很容易就想到了. 这里再考虑到C[i+j]的这个元素肯定是由A[i]或B[j]组成(即A的最末尾或B的最末尾,因为要保证原来的order) 所以这就变成了dp[i][j] = dp[i-1][j] | dp[i][j-1]  (当然这是A[i]=B[j]=C[i+j])的情况.

POJ 3436 ACM Computer Factory 【网络流】【北大ACM/ICPC竞赛训练】

我ac掉网络流的第一题! 先总结一下网络流的一些算法吧,首先是Ford-Fulkerson算法,这个算法是保证了众多网络流算法的[正确性],其他算法也是基于其[优化]得到的.Ford的算法在于引入"反向边"的概念,反向边就是反悔边,代表你给修正以前走了的边一个机会.为什么反向边是对的呢,凭空加进来一条边真的大丈夫吗,关于这个有相关正确性的证明,我也说不清楚只能直觉上去理解. 之后是Edmonds-Karp即最短增广路算法,顾名思义,每次都找到达汇点边数最少的增广路,由此避免一些特定的消

poj 2411 Mondriaan&#39;s Dream(状压DP)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12232   Accepted: 7142 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

POJ 3311 Hie with the Pie (状压DP)

状态压缩DP dp[i][j]表示在i状态(用二进制表示城市有没有经过)时最后到达j城市的最小时间 转移方程dp[i][j]=min(dp[i][k]+d[k][j],dp[i][j]) d[k][j]是k城市到j城市的最短距离 要先用flody处理 #include<bits.stdc++.h> using namespace std; int d[20][20],dp[1<<11][20]; int n,m; void flody() { for(int k=0;k<=n

【POJ 3254】 Corn Fields(状压DP)

[POJ 3254] Corn Fields(状压DP) Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10891   Accepted: 5705 Description Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parce