设为首页 加入收藏

TOP

一道DP练习题详解(一)
2013-12-12 14:36:53 来源: 作者: 【 】 浏览:482
Tags:一道 习题 详解

    这道题在黑书里面介绍的非常详细,我这里贴一下使用滚动数组来优化的代码。

    用dp[x][y][z]存,当第z步的时候左脚在x,右脚在y的情况。

    dp[x][y][z] = min(dp[a[i]][y][i + 1] + doit(x , a[i]) , dp[x][a[i]][i + 1] + doit(y , a[i])) ;

    #define N 100005

    int dp ;

    int a[N] ;

    int doit(int a ,int b) {

    if(a == b)return 1 ;

    if(a == 0 || b == 0)return 2 ;

    if(a == 1) {

    if(b == 2 || b == 4 || b == 0)return 3 ;

    return 4 ;

    }

    if(a == 2) {

    if(b == 3 || b == 1 || b == 0)return 3 ;

    return 4 ;

    }

    if(a == 3) {

    if(b == 2 || b == 4 || b == 0)return 3 ;

    return 4 ;

    }

    if(a == 4) {

    if(b == 1 || b == 3 || b == 0)return 3 ;

    return 4 ;

    }

    }

    int main() {

    while(cin 》 a[0] , a[0]) {

    int num = 1 ;

    while(1) {

    cin 》 a[num] ;

    num ++ ;

    if(a[num - 1] == 0)break ;

    }

    num -- ;

    for (int i = 0 ; i < 2; i ++ ){

    for (int j = 0 ; j < 5 ; j ++ ){

    for (int k = 0 ; k < 5; k ++ ){

    dp[j][k][i] = inf ;

    }

    }

    }

    for (int i = 0 ; i < 5 ; i ++ )dp[i][a[num - 1]][num % 2] = dp[a[num - 1]][i][num % 2] = 0 ;

    for (int i =  num - 1 ; i >= 0 ; i -- ) {

    for (int j = 0 ; j < 5 ; j ++ ) {

    for (int k = 0 ; k < 5 ; k ++ ) {

    dp[j][k][i % 2] = min(dp[a[i]][k][(i + 1) % 2] + doit(j , a[i]) , dp[j][a[i]][(i + 1) % 2] + doit(k ,a[i])) ;

    }

    }

    }

    cout 《 dp[0][0][0] 《 endl;

    }

    return 0 ;

    }

    POJ 3311 裸TSP --08.07

    #include <set>

    #include <map>

    #include <stack>

    #include <cmath>

    #include <queue>

    #include <cstdio>

    #include <string>

    #include <vector>

    #include <iomanip>

    #include <cstring>

    #include <iostream>

    #include <algorithm>

    #define Max 2505

    #define ll long long

    #define PI acos(-1.0)

    #define inf 0x2fffffff

    #define LL(x) ( x 《 1 )

    #define bug puts("here")

    #define PII pair<int,int>

    #define RR(x) ( x 《 1 | 1 )

    #define mp(a,b) make_pair(a,b)

    #define mem(a,b) memset(a,b,sizeof(a))

    #define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i )

    using namespace std;

    inline void RD(int &ret) {

    char c;

    do {

    c = getchar();

    } while(c < '0' || c > '9') ;

    ret = c - '0';

    while((c=getchar()) >= '0' && c <= '9')

    ret = ret * 10 + ( c - '0' );

    }

    inline void OT(int a) {

    if(a >= 10)OT(a / 10) ;

    putchar(a % 10 + '0') ;

    }

    #define N 12

    int Map[N][N] ;

    int n ;

    int dp[1 《 N][N] ;

    int main() {

    while(cin 》 n , n){

    for (int i = 0 ; i < n + 1 ; i ++ ){

    for (int j = 0 ; j < n + 1 ; j ++ ){

    cin 》 Map[i][j] ;

    }

    }//floyd,注意MAP[I][J] != MAP[J][I]

    for (int i = 0 ; i < n + 1 ; i ++ ){

    for (int j = 0 ; j < n + 1 ; j ++ ){

    for (int k = 0 ; k < n + 1 ; k ++ ){

    Map[i][j] = min(Map[i][j] , Map[i][k] + Map[k][j]) ;

    }

    }

    }

    for (int i = 0 ; i < (1 《 (n + 1)) ; i ++){

    for (int j = 0 ; j < n + 1 ; j ++ )dp[i][j] = inf ;

    }//从0出发,回到0.可重复走路径

    dp[0][0] = 0 ;

    for (int i = 0 ; i < (1 《 (n + 1)) ; i ++ ){

    for (int j = 0 ; j < n + 1 ; j ++ ){

    if(i & (1 《 j) == 0)continue ;

    for (int k = 0 ; k < n + 1 ; k ++ ){

    if(k == j)continue ;//所以这里不需要判断if(i & (1 《 k))continue ;

    int tt = i | (1 《 k) ;

    dp[tt][k] = min(dp[i][j] + Map[j][k] , dp[tt][k]) ;

    }

    }

    }

    cout 《 dp[(1 《 (n + 1)) - 1][0] 《 endl;

    }

    return 0 ;

    }

    POJ 1185 炮兵阵地 --08.07

    经典的状压dp.

    网上的解释很多也很详细,这里就不多解释了。

     

首页 上一页 1 2 3 4 5 6 7 下一页 尾页 1/7/7
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇根据括号匹配求区间DP 下一篇计算气球半径让其不相交

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·Libevent C++ 高并发 (2025-12-26 00:49:30)
·C++ dll 设计接口时 (2025-12-26 00:49:28)
·透彻理解 C 语言指针 (2025-12-26 00:22:52)
·C语言指针详解 (经典 (2025-12-26 00:22:49)
·C 指针 | 菜鸟教程 (2025-12-26 00:22:46)