【练习07】 DFS 1011 蜘蛛牌
来源:互联网 发布:计算睡眠网络断开 编辑:程序博客网 时间:2024/06/01 21:24
算法思路:
1. DFS,暴力搜索,需要剪枝;
2.1. dp(递归法),关键是递归函数的构造,如果想到了“状态转移方程”这一步是比较容易写出代码的;
2.2. dp(递推),关键是递推的初值和递推的顺序。当然首先需要想出状态转移方程。
下面分别列出这2种方法的详细分析:
方法一:125msAC,最慢的,思路很直接,看代码。
代码如下:
#include<iostream>#include<cmath>#include<algorithm>using namespace std;/*简直就是一个悲剧 自己写的错误百出 最后还是要学习别人的代码 才能AC*/const int INF=100000000;int vis[12];int a[12],ans;void DFS(int cur,int temp)//cur代表已经移动了几张牌,temp代表目前移动耗费的步数,把步数写在这里解决了我一直的疑惑{ if(temp>=ans)return; //剪枝 太重要了!! if(cur==9) //原来写成10,只用移动9次 10是固定不变的 这里需要思考 我原先做的时候什么都没想 就一个劲儿的枚举 { ans=temp; //原来temp=0,既然进入了这个语句 就已经确保当前值比原来的要优化 return; //回溯,可以自然解决改temp的问题 } for(int i=1;i<10;i++)//递归里写上这句就是一个全排列了(+下面的判重) { if(!vis[i]) { for(int k=i+1;k<=10;k++)//这个用来确定i牌要移到什么位置 { if(!vis[k])//比如要移1了,如果2,3,4,5都已经被移动过了 那么这几张牌必定叠放在6的下面,所以要移到6的位置 { vis[i]=1; DFS(cur+1,temp+abs(a[i]-a[k])); break;//注意不要再这个地方回溯 如果回溯了 就像是又一个全排列 而且牌得移动不合理,比如2移到6了,结果回溯就直接跳过3~6到了7的下面 } } vis[i]=0;//这里回溯 } } return ;}int main(){ int cas,s; cin>>cas; while(cas--) { for(int i=1;i<=10;i++) { cin>>s; a[s]=i;//牌面为i的牌所在的位置 } memset(vis,0,sizeof(vis)); ans=INF; DFS(0,0); cout<<ans<<endl; }}转载自:http://www.cnblogs.com/sook/archive/2011/03/27/1996775.html
方法2:
当子问题的数量不多时,通常我们能够比较清晰地求出最优解的结构,然后理清各种状态之间转移的过程。但是,如果一个动态规划拥有多个子结构时,我们往往会觉得无从下手,面对这种情况,我们可以考虑下枚举子结构,然后得到动态规划的最优解。而且,有时候我们在枚举子结构时,还要运用另外一些最优结构。我们看看下面几个例子。
1.hdoj 1584 蜘蛛牌
我们定义dp[i][j]表示从牌的大小为i到牌的大小为j这一串牌,通过移动得到满足条件的一堆牌的最小步数。对于牌1来说,他必须移到到2的上面,但是我们不知道,当他移到2位置上时2到底在哪,所以我们可以枚举2的位置。这样我们就得到了状态转移方程:dp[1][10] = dp[2][i] + dp[i][10] + dis[1][i] ; (2<=j<=10, dis[i][j]表示牌i和牌j之间的距离)。这样我们就用子问题的最优解构造出了原问题的最优解了。接下来我们可以利用子问题的最优解来递归定义问题的最优解。当然我们可以用递推来实现。这样问题便解决了。
转移方程:dp[l][r] = min{dp[l +1][j] + dp[j][r] + dis[l][j]}, j在区间[l + 1, r], j为整数。 其中dp的过程需要枚举所有可能的j。
//模板开始#include <string> #include <vector> #include <algorithm> #include <iostream> #include <sstream> #include <fstream> #include <map> #include <set> #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime>#include<iomanip>#include<string.h>#define SZ(x) (int(x.size()))using namespace std;int toInt(string s){istringstream sin(s); int t; sin>>t; return t;}template<class T> string toString(T x){ostringstream sout; sout<<x; return sout.str();}typedef long long int64;int64 toInt64(string s){istringstream sin(s); int64 t; sin>>t;return t;}template<class T> T gcd(T a, T b){ if(a<0) return gcd(-a, b);if(b<0) return gcd(a, -b);return (b == 0)? a : gcd(b, a % b);}#define ifs cin//模板结束(通用部分)#define INF 1<<30int p[12];int dis[12][12];int dp[12][12];void init(){for(int i = 1; i <= 10; i++){for(int j = 1; j <= 10; j++){dp[i][j] = INF;dis[i][j] = abs(p[i] - p[j]);}}}int solve(int l, int r){int &t = dp[l][r];int s;if(l == r){return 0; }if(r - l == 1){return dis[l][r];}if(t != INF){return t;}for(int i = l + 1; i <= r; i++){s = solve(l + 1, i) + dis[l][i] + solve(i, r);if(t > s){t = s;}}return t;}//【练习07】 DFS 1011 蜘蛛牌int main(){//ifstream ifs("shuju.txt", ios::in);int T;int a;ifs>>T;for(int i = 0; i < T; i++){for(int j = 1; j <= 10; j++){ifs>>a;p[a] = j;}init();int ans = solve(1, 10);cout<<ans<<endl;}return 0;}
递推实现,要深刻理解len,它表示dp[i][j]中j - i的最大长度,初始化的时候可以看做 len = 2,因为这时候还只可以确定dp[i][i + 1], 所以后面循环递推的时候需要让len从3开始逐步增长,直到10。
dp[i][i + 1] = dis[i][i + 1];
dp[i][i] = 0;
这两句初始化也很关键。
15msAC,代码如下:
//模板开始#include <string> #include <vector> #include <algorithm> #include <iostream> #include <sstream> #include <fstream> #include <map> #include <set> #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime>#include<iomanip>#include<string.h>#define SZ(x) (int(x.size()))using namespace std;int toInt(string s){istringstream sin(s); int t; sin>>t; return t;}template<class T> string toString(T x){ostringstream sout; sout<<x; return sout.str();}typedef long long int64;int64 toInt64(string s){istringstream sin(s); int64 t; sin>>t;return t;}template<class T> T gcd(T a, T b){ if(a<0) return gcd(-a, b);if(b<0) return gcd(a, -b);return (b == 0)? a : gcd(b, a % b);}#define ifs cin//模板结束(通用部分)#define INF 1<<8int p[12];int dis[12][12];int dp[12][12];void init(){for(int i = 1; i <= 10; i++){for(int j = 1; j <= 10; j++){dp[i][j] = INF;dis[i][j] = abs(p[i] - p[j]);}dp[i][i + 1] = dis[i][i + 1];dp[i][i] = 0;}}int solve(){for(int len = 3; len <= 10; len++){for(int i = 1; i + len - 1 <= 10; i++){for(int j = i + 1; j <= i + len - 1; j++){if(dp[i + 1][j] + dp[j][i + len - 1] + dis[i][j] < dp[i][i + len - 1]){dp[i][i + len - 1] = dp[i + 1][j] + dp[j][i + len - 1] + dis[i][j];}}}}return dp[1][10];}//【练习07】 DFS 1011 蜘蛛牌int main(){//ifstream ifs("shuju.txt", ios::in);int T;int a;ifs>>T;for(int i = 0; i < T; i++){for(int j = 1; j <= 10; j++){ifs>>a;p[a] = j;}init();int ans = solve();cout<<ans<<endl;}return 0;}
转载自:http://www.cnblogs.com/crazyac/articles/1996475.html
自己看过上面的递归版dp,加了记忆化,改进了一下,0msAC,代码如下:
#include <iostream>#include <cmath>using namespace std;#define INF 1<<30int num[11], dis[11][11];int dp[11][11];void init() {int i, j, a;for( i=1; i<=10; ++i ) {scanf( "%d", &a );num[a] = i;}for( i=1; i<=10; ++i ) {for( j=1; j<=10; ++j ) {dis[i][j] = abs( num[i] - num[j] );dp[i][j] = INF;}}}int solve(int l, int r ) {int i, s;if( l == r ) return 0;if( r - l == 1 ) return dis[l][r];if(dp[l][r] != INF){return dp[l][r];}for( i=l+1; i<=r; ++i ) {s = solve( l+1, i ) + solve(i, r) + dis[l][i];if( dp[l][r] > s ) dp[l][r] = s;}return dp[l][r];}int main() {//freopen( "c:/aaa.txt", "r", stdin );int T;scanf( "%d", &T );while( T-- ) {init();printf( "%d\n", solve(1, 10));}return 0;}
- 【练习07】 DFS 1011 蜘蛛牌
- HDU1584:蜘蛛牌(DFS)
- 【DFS】HDU1584蜘蛛牌
- HDOJ1584蜘蛛牌【DFS】
- hdu1584 蜘蛛牌dfs
- HDU1584 蜘蛛牌(DFS)
- hdu 1584蜘蛛牌(DFS)
- hdu 1584 蜘蛛牌(dfs)
- hdu1584蜘蛛牌(dfs)
- hdu 蜘蛛牌(DFS + 剪枝)
- hdu--1548--dfs--蜘蛛牌
- hdu1584 蜘蛛牌(DFS)
- HDU-1584 蜘蛛牌【dfs】
- dfs hdu 1584 蜘蛛牌
- hdu 1584 蜘蛛牌 DFS解法
- HDU 1584 蜘蛛牌(DFS)
- HDU1584 蜘蛛牌 [DFS简单题]
- hdu 1584 蜘蛛牌【dfs+简单剪枝】
- TCP并发服务器之进程
- android socket 理论
- android binder机制之--(我是Service Manager)
- 常用字符集编码详解:ASCII 、GB2312、GBK、GB1803...
- java多线程1-如何创建线程
- 【练习07】 DFS 1011 蜘蛛牌
- uva 540 Team Queue
- C# 文件存在性判断
- RTX腾讯通基本功能
- Openfire 离线消息的处理机制
- 想要将UIButton设置背景色
- 1130-host ... is not allowed to connect to this MySql server
- FindingClosestObject
- mysql绑定参数bind_param原理以及防SQL注入