不知道什么时候,丢掉了我很感兴趣的算法,也不在更新博客了。但是这段时间,总感觉生活中少了些什么,常常感觉不太习惯,原来我把学习算法和写博客冷落了好几个月了。好习惯就要一直坚持下去,也希望大家坚持自己认为正确的习惯。这样活着才有意思哈。
/****************************************************
* 这道题目一看就是动态规划,但是就是不知道如何写状态方程。
* 后来参考了别人的解题报告才知道。f[i][j][k] = max{f[i-1][k][l] + c[j]}
* 其中f[i][j][k]标示第i行状态为s[j]第i-1行状态为s[k]的时候能放士兵的最大
* 值。然后只需要枚举j就可以了。看上去状态很多,实际上算来每行也就60多种。
* 所以j<60,k < 60.而每次只需要两行,所以i可以用滚动数组,i< 2.
*****************************************************/
这里我用了滚动数组,实际上直接开f[101][61][61]也行,这样就不用滚动数组了,但是内存空间却多用了不少。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char map[101][11];
int origMap[101], row,num, col, s[61], c[61], f[2][61][61];
int main()
{
memset(origMap, 0, sizeof(origMap));
memset(s, 0, sizeof(s));
memset(c, 0, sizeof(c));
scanf("%d %d", &row, &col);
//getchar();
for (int i = 0; i < row; ++ i)
{
scanf("%s", map[i]);
}
for (int i = 0; i < row; ++ i)
{
for (int j = 0; j < col; ++ j)
{
//scanf("%c", & map[i][j]);
if (map[i][j] == 'H')
{
origMap[i] += (1 << j);//初始状态,不能放的为1
}
}
//getchar();
}
num = 0;
//符合要求的所有状态
for (int k = 0; k < (1 << col); ++ k)
{
int m = k;
if (((m << 1) & k) || ((m << 2) & k))
{
continue;
}
c[num] = m % 2;
while (m = (m >> 1))
{
c[num] += m % 2;
}
s[num ++ ] = k;
}
int roll = 0;
for (int i = 0; i < row; ++ i)
{
for (int j = 0; j < num; ++ j)
{
if (s[j] & origMap[i])//第i行第j个状态是否和最初的状态冲突
{
continue;
}
if (i == 0)
{
f[roll][j][0] = c[j];
}
else if (i == 1)
{
for (int k = 0; k < num; ++ k)
{
if (s[k] & origMap[i - 1])//i-1行是否冲突
{
continue;
}
if (s[j] & s[k])//i行和i-1行是否冲突
{
continue;
}
if (f[roll][j][k] < f[(roll + 1) % 2][k][0] + c[j])
{
f[roll][j][k] = f[(roll + 1) % 2][k][0] + c[j];
}
}
}
else
{
for (int k = 0; k < num; ++ k)
{
if (s[k] & origMap[i - 1])
{
continue;
}
if (s[j] & s[k])
{
continue;
}
for (int l = 0; l < num; ++ l)
{
if (s[l] & origMap[i - 2])
{
continue;
}
if ((s[k] & s[l]) | (s[j] & s[l]))
{
continue;
}
if ( f[roll][j][k] < f[(roll + 1) % 2][k][l] + c[j] )
{
f[roll][j][k] = f[(roll + 1) % 2][k][l] + c[j];
}
}
}
}
}
roll = (roll + 1) % 2;
}
roll = (roll + 1) % 2;
//求出最大值
int mMax = 0;
for (int i = 0; i < num; ++ i)
{
for (int j = 0; j < num; ++ j)
{
if (mMax < f[roll][i][j])
{
mMax = f[roll][i][j];
}
}
}
printf("%d\n", mMax);
return 0;
}