【練習07】 DFS 1011 蜘蛛牌

來源:互聯網
上載者:User

演算法思路:

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。

遞迴實現, 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<<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;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.