一,状态压缩不讲了,很简单的;
二,讲讲最核心的算法,怎么算过来的;
a, 首先,动态规划是在求出子问题的基础上,并子问题不能变,在这个基础上,慢慢向后推,求出最终问题;
b, 难点就在这里,子问题是改变的,在这一行的数受到上一行和上上一行的影响,是改变的;
c, 但是在推到第3行时,表示第3行的状态时,包括第前2行,一起算到第3行,这样,在求第4行时,只需要看第4行的状态(包括第4行的前2行)的所用状态;
第3行的第一种状态的后二个状态数,与第4行的一种状态的前二个状态数匹配,成,就加上第4行的后一个状态数的炮的数量,进行求最大炮的数量;依次类推;
算完后,只要将最后一行的所有状态的炮的数量输出就好了;
三,我输出路径的方法;
每走一流程,到下一步,下一步,就会记录这一步的的位置;
这样,只要最后的位置,就可以反向推出一种方案;
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
const int N = 101;
const int M = 10;
int m,n;
int maze[N];
char arg[N][M];
int mazeAloneState[N][60];
int mazeAllState[N][216000][5];
int result,finish;
int minA,minB,minC;
int getNumber(int num){
int count=0;
int i;
for(i=0; i<m; i++){
if(num&(1<<i))
count++;
}
return count;
}
int getSum(int n){
if(n==0) return 0;
if(n>=59) return 4;
if(n>=38) return 3;
if(n>=11) return 2;
if(n>=1) return 1;
}
void showAll(int local){
int i=0;
if(local < 2) return;
printf("*****************\n");
while(mazeAllState[local][i][0] != -1){
printf("%6d %6d %6d %6d %6d\n",
mazeAllState[local][i][0], mazeAllState[local][i][1], mazeAllState[local][i][2], mazeAllState[local][i][3],
mazeAllState[local][i][4] );
i++;
}
printf("*****************");
}
void subA(){
int i,j,k,max,temp,min;
max = 0;
for(i=59; i>=0; i--){
if(mazeAloneState[0][i] != -1){
temp = getSum(i);
if(max<=temp){
max = temp;
minA = i;
}
}
}
result = max;
}
void subB(){
int i,j,max=0,temp;
for(i=59; i>=0; i--){
for(j=59; j>=0; j--){
if(mazeAloneState[0][i]==-1 || mazeAloneState[1][j] == -1)
continue;
if( !( mazeAloneState[0][i] & mazeAloneState[1][j] ) ){
temp = getSum(i) + getSum(j);
if(max<=temp ){
max = temp;
minA=i;
minB=j;
}
}
}
}
result = max;
}
void subC(){
int i,j,k,max=0,temp,count = 0;
for(i=59; i>=0; i--){
for(j=59; j>=0; j--){
for(k=59; k>=0; k--){
if(mazeAloneState[0][i] == -1 || mazeAloneState[1][j] == -1 || mazeAloneState[2][k] == -1)
continue;
if( !(mazeAloneState[0][i]&mazeAloneState[1][j]) && !(mazeAloneState[0][i]&mazeAloneState[2][k])
&& !(mazeAloneState[2][k]&mazeAloneState[1][j]) ) {
temp = getSum(i) + getSum(j) + getSum(k);
mazeAllState[2][count][0] = mazeAloneState[0][i];
mazeAllState[2][count][1] = mazeAloneState[1][j];
mazeAllState[2][count][2] = mazeAloneState[2][k];
mazeAllState[2][count][3] = temp;
mazeAllState[2][count][4] = 0;
count++;
if(max<=temp){
max=temp;
minA=i;
minB=j;
minC=k;
}
}
}
}
}
result = max;
}
void solveAll(){
if(n<4) return ;
int number = 3;
while(number < n){
int i,j,k,minA,minB,minC,max=0,temp,count = 0;
for(i=59; i>=0; i--){
for(j=59; j>=0; j--){
for(k=59; k>=0; k--){
if(mazeAloneState[number-2][i] == -1 || mazeAloneState[number-1][j] == -1 || mazeAloneState[number][k] == -1)
continue;
if( !(mazeAloneState[number-2][i]&mazeAloneState[number-1][j]) && !(mazeAloneState[number-2][i]&mazeAloneState[number][k])
&& !(mazeAloneState[number][k]&mazeAloneState[number-1][j]) ) {
temp = getSum(k);
mazeAllState[number][count][0] = mazeAloneState[number-2][i];
mazeAllState[number][count][1] = mazeAloneState[number-1][j];
mazeAllState[number][count][2] = mazeAloneState[number][k];
mazeAllState[number][count][3] = temp;
mazeAllState[number][count][4] = 0;
count++;
if(max<=temp){
max=temp;
}
}
}
}
}
number++;
}
}
void getNext(int next[], int m){
int i,j;
for(i=m-1,j=0; i>=0; i-- ){
next[j++] = 1<<i;
}
}
void init(int n, int m){
memset(maze, 0, sizeof(int)*N);
memset(mazeAloneState, -1, sizeof(int)*N*60);
memset(mazeAllState, -1, sizeof(int)*N*216000*5);
int i,j,flag,temp;
char ch;
int *next = new int[m];
getNext(next, m);
for(i=0; i<n; i++){
for(j=0; j<m; j++){
cin>>ch;
arg[i][j] = ch;
if(ch == 'H')
maze[i] += next[j];
}
}
//初始化一行的状态
int count=0,a,b,c,h,k;
for(i=0; i<n; i++){
mazeAloneState[i][0] = 0;
count=1;
for(j=0; j<m; j++){
temp = 1<<j;
if( !(temp&maze[i]) )
mazeAloneState[i][count++] = temp;
}
count=11;
for(j=0; j<m; j++){
for(k=j+3; k<m; k++){
a = 1<<j; b = 1<<k;
temp = a + b;
if( !(temp&maze[i]) )
mazeAloneState[i][count++] = temp;
}
}
count=39;
for(j=0; j<m; j++){
for(k=j+3; k<m; k++){
for(h=k+3; h<m; h++){
a=1<<j; b=1<<k; c=1<<h;
temp = a + b + c;
if( !(temp&maze[i]) )
mazeAloneState[i][count++] = temp;
}
}
}
count=59;
if( !(585&maze[i]) && m==10){
mazeAloneState[i][count] = 585;
}
}
solveAll();
}
void solve(){
int i,j,k,count,temp,a,b,c,e,f;
if(n==0){result = 0; return;}
if(n==1){subA(); return;}
if(n==2){subB(); return;}
if(n>=3){
subC();
for(i=3; mazeAloneState[i][0] != -1; i++ ){
for(j=0; mazeAllState[i][j][0] != -1; j++){
for(k=0; mazeAllState[i-1][k][0] != -1; k++){
a = mazeAllState[i][j][0];
b = mazeAllState[i][j][1];
c = mazeAllState[i][j][2];
temp = getNumber(c);
e = mazeAllState[i-1][k][1];
f = mazeAllState[i-1][k][2];
if(a==e && b==f)
if(mazeAllState[i-1][k][3]+temp > mazeAllState[i][j][3]){
mazeAllState[i][j][3] = mazeAllState[i-1][k][3]+temp;
mazeAllState[i][j][4] = k;
}
}
}
}
}
//找到最大值;
int max = 0;
for(i=0; mazeAllState[n-1][i][3] != -1; i++){
if( mazeAllState[n-1][i][3]>max ){
max = mazeAllState[n-1][i][3];
finish = i;
}
}
result = max;
}
void inputPath(){
printf("\n***** 倒序 ******\n");
if(n==1) {
printf("path = %d\n",mazeAloneState[0][minA]);
return ;
}
if(n==2){
printf("path = %d\n",mazeAloneState[1][minB]);
printf("path = %d\n",mazeAloneState[0][minA]);
return ;
}
if(n==3){
printf("path = %d\n",mazeAloneState[2][minC]);
printf("path = %d\n",mazeAloneState[1][minB]);
printf("path = %d\n",mazeAloneState[0][minA]);
return ;
}
int i,j,k,temp;
for(i=n-1; i>=3; i--){
printf("path = %d\n",mazeAllState[i][finish][2]);
finish = mazeAllState[i][finish][4];
}
printf("path = %d\n",mazeAllState[i][finish][2]);
printf("path = %d\n",mazeAllState[i][finish][1]);
printf("path = %d\n",mazeAllState[i][finish][0]);
}
int main()
{
cin>>n>>m;
init(n,m);
solve();
printf("result = %d\n",result);
inputPath();
}