程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> uva 1291 - Dance Dance Revolution ( dp )

uva 1291 - Dance Dance Revolution ( dp )

編輯:C++入門知識

題目大意

 

如上圖,這是一個跳舞機,初始狀態兩個腳都在0,  狀態表示為(0, 0), 然後跳舞機會給你一系列舞步方向,例如2,3,4,2,3.......

每次你必須選擇一只腳移動到對應數字方向的各格子上。

例如從初始狀態(0,0),要移到1, 可以選擇左腳或者右腳移上去,對應的狀態為(1, 0), (0,1)

有一個限制,除了初始狀態可以是(0, 0),之後的兩只腳就不能再同時在一個格子上!

移動腳要耗費體力, 從0移動到其它各自都是耗費2, 從1,2,3,4之間,如果是移動到相鄰的格子,比如1->2, 1->4, 3->2, 4->3,耗費體力3

如果是移動到對面的格子,比如1->3, 2->4,耗費體力4。

如果某一步,停止不動,耗費體力1

給一串方向,問最少用多少體力可以完成這些動作?

 

 

 

思路
f(i, j, k), 表示第i步,狀態為(j,k)時花費的最少體力
那麼不難推出轉移方程式:

假設當前這個舞步是在s,那麼符合這一步的所有狀態有:
f(i, 0..4, s),  f(i, s, 0...4)

然後可以根據上面的狀態推出下一舞步的最少體力話費

假設下一舞步是next

那麼

如果f(i, j, s), (0<=j<=4)狀態可達
則可推出下一個的狀態
f(i+1, j, s) = f(i, j, k) + 1; // 停在當前不動
f(i+1, next, s) = min{ f(i, j, s) + consume(j, next)}
f(i+1, j, next) = min{ f(i, j, s) + consume(s, next)}

同理,如果f(i, s, j), (0<=j<=4)狀態可達
也可推出下一個狀態:
f(i+1, s, j) = f(i, j, k) + 1; // 停在原地不動
f(i+1, next, j) = min{ f(i, s, j) + consume(s, next)}
f(i+1, s, next) = min{ f(i, s, j) + consume(j, next)}

 

 

 

 


代碼
 

/**========================================== * 
  This is a solution for ACM/ICPC problem * * 
  @source:uva-1291 Dance Dance Revolution * 
  @author: shuangde *  
 @blog: blog.csdn.net/shuangde800 *  
 @email: [email protected] *===========================================*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long int64;
const int INF = 0x3f3f3f3f;
const int MAXN = 10010;
int n;int dir[MAXN];
int f[MAXN][5][5];
inline int consume(int from, int to){    if(from==to) return 1; 
   if(from==0 || to==0) return 2;  
  int res = abs(from-to);  
  if(res == 1 || res==3) return 3;  
  if(res == 2) return 4;
}int main(){    while(~scanf("%d", &dir[0]) && dir[0]){        n = 1;   
     while(~scanf("%d", &dir[n]) && dir[n]) ++n;      
  memset(f, INF, sizeof(f));     
   for(int i=0;
 i<=4; ++i)            f[0][0][i] = f[0][i][0] = consume(0, i); 
       for(int i=0; i<n-1; 
++i){            int s = dir[i];    
        int next = dir[i+1];     
       for(int j=0;
 j<=4; 
++j) if(s!=j){                if(f[i][s][j] != INF){                
    f[i+1][s][j] = min(f[i+1][s][j], f[i][s][j] + 1);  
                  for(int k=0; 
k<=4; 
++k){                        f[i+1][next][j] = min(f[i+1][next][j], f[i][s][j] +consume(s, next));   
                      f[i+1][s][next] = min(f[i+1][s][next], f[i][s][j] +consume(j, next));  
                   }                 }                if(f[i][j][s] != INF){         
           f[i+1][j][s] = min(f[i+1][j][s], f[i][j][s] + 1);  
                   for(int k=0; k<=4; 
++k){                        f[i+1][next][s] = min(f[i+1][next][s], f[i][j][s] +consume(j, next));   
                      f[i+1][j][next] = min(f[i+1][j][next], f[i][j][s] +consume(s, next));       
              }                 }            }        }         int ans = INF;       
 int s = dir[n-1];   
     for(int i=0; 
i<=4; 
++i)if(i!=s){            ans = min(ans, min(f[n-1][i][s], f[n-1][s][i]));      
          }        printf("%d\n", ans);  
  }    return 0;} 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved