poj1185兴趣还是要坚持滴。。

不知道什么时候,丢掉了我很感兴趣的算法,也不在更新博客了。但是这段时间,总感觉生活中少了些什么,常常感觉不太习惯,原来我把学习算法和写博客冷落了好几个月了。好习惯就要一直坚持下去,也希望大家坚持自己认为正确的习惯。这样活着才有意思哈。

 

/****************************************************
* 这道题目一看就是动态规划,但是就是不知道如何写状态方程。
* 后来参考了别人的解题报告才知道。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;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值