2031 - Dance Dance Revolution
Asia - Shanghai - 2000/2001
//https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=32
看代码中的注释
View Code
1 //怀特先生跳舞 2 #include <cstdio> 3 #define MAXN 100005 4 #define INF 100000000 5 int cur; 6 int a[MAXN]; 7 //该过程自然不会出现最后答案中有两只脚踩在同一位置,因为如果已有一只脚踩在那里,完全会是该脚再动一下,而不是把另一只脚也移过来 8 //逆推,因为从初试位置(0,0)到跳完一系列舞步所耗费的体力可以想成从最后一个舞步开始,跳到初试位置耗费的体力 9 int d[5][5][MAXN];//d[i][j][k]表示在将要跳舞步k时,左脚踩在位置i,右脚踩在位置j时已耗费的最少体力 10 int effort[5][5]= //effort[a][b]表示从位置a移动到位置b要耗费的最少体力 11 { 12 {1,2,2,2,2}, 13 {2,1,3,4,3}, 14 {2,3,1,3,4}, 15 {2,4,3,1,3}, 16 {2,3,4,3,1} 17 }; 18 int main() 19 { 20 // freopen("in.cpp","r",stdin); 21 while(1) 22 { 23 int fis; 24 scanf("%d",&fis); 25 if(fis == 0) break; 26 cur = 0; 27 while(1) 28 { 29 a[++cur] = fis; 30 scanf("%d",&fis); 31 if(fis == 0) break; 32 } 33 int i,j,k,t; 34 for(k =0; k <= cur; ++k)//因为是要算最少,所以初始值是正无穷 35 for(i=0; i < 5; ++i) 36 for(j=0; j < 5; ++j) 37 d[i][j][k] = INF; 38 for(i=0; i<5; ++i)//逆推最后总是会有一只脚站在a[cur]位置上,所以为0 39 d[i][a[cur]][cur] = 0; 40 for(j=0; j<5; ++j) 41 d[a[cur]][j][cur] = 0; 42 d[a[cur]][a[cur]][cur] = INF; 43 a[0] = 0;//舞步0是自己添加的为0,最后两只脚都踩在位置0 44 for(k = cur-1; k >= 0; --k) 45 { 46 for(i=0; i<5; ++i) 47 { 48 for(j=0; j<5; ++j) 49 { 50 t = d[a[k+1]][j][k+1] + effort[a[k+1]][i];//跳k+1步时用的是左脚,转移方程 51 if(d[i][j][k] > t) 52 d[i][j][k] = t; 53 t = d[i][a[k+1]][k+1] + effort[a[k+1]][j];//用的是右脚,转移方程 54 if(d[i][j][k] > t) 55 d[i][j][k] = t; 56 } 57 } 58 } 59 printf("%d\n",d[0][0][0]); 60 } 61 return 0; 62 }