多维动态规划好题
题目大意:给定一个5行9列的中国象棋棋盘(一半),棋盘上红方只剩一个已过河的卒,现黑方让红方连续走k步,求红方最多能吃掉黑方多少棋子。k<=100
分析:直接搜索的话肯定会超时(指数级别的复杂度),可以考虑根据卒的位置和其他棋子是否被吃掉来设计状态进行动态规划,关键在于状态的设计,因为卒只能向前冲不能后退,所以后面的行不影响结果,而前面的行中的棋子仍处于初始状态,只有当前行中的棋子的状态需要保存,可以用dp[i][j][k][left][right]表示卒位于i行j列还可以走k步,当前行最左走到left,最右走到right时最多能吃掉多少棋子,状态设计出来了,状态转移方程也就不难了,边界条件为k=0时结果为0。
1 #include <stdio.h> 2 #include <string.h> 3 #define MAX(a,b) ((a)>(b)?(a):(b)) 4 char g[5][9]; 5 int d[5][9][101][9][9]; 6 int dp(int i,int j,int k,int left,int right) 7 { 8 int tmp=0; 9 if(d[i][j][k][left][right]!=-1) return d[i][j][k][left][right]; 10 if(!k) return d[i][j][k][left][right]=0; 11 if(i>0) 12 { 13 tmp=MAX(tmp,dp(i-1,j,k-1,j,j)+g[i-1][j]); 14 } 15 if(j>0) 16 { 17 if(j>left) tmp=MAX(tmp,dp(i,j-1,k-1,left,right)); 18 else tmp=MAX(tmp,dp(i,j-1,k-1,j-1,right)+g[i][j-1]); 19 } 20 if(j<8) 21 { 22 if(j<right) tmp=MAX(tmp,dp(i,j+1,k-1,left,right)); 23 else tmp=MAX(tmp,dp(i,j+1,k-1,left,j+1)+g[i][j+1]); 24 } 25 return d[i][j][k][left][right]=tmp; 26 } 27 int main() 28 { 29 int i,j,t,k,si,sj; 30 char c; 31 scanf("%d",&t); 32 while(t--) 33 { 34 scanf("%d",&k); 35 for(i=0;i<5;i++) 36 { 37 getchar(); 38 for(j=0;j<9;j++) 39 { 40 scanf("%c",&c); 41 g[i][j]=(c=='K'?1:0); 42 if(c=='L') si=i,sj=j; 43 } 44 } 45 memset(d,-1,sizeof(d)); 46 printf("%d\n",dp(si,sj,k,sj,sj)); 47 } 48 return 0; 49 }