POJ - 2385 Apple Catching解题报告

题目大意:

有个牛,好多题了,都是牛。然后她想吃苹果。有两个树,单位时间,在一棵树上会掉下来一个苹果。她必须在这个时间正好站到了这棵树下,才能吃到这个苹果。现在给你一共有T(1000)个单位时间,以及每个单位时间是哪一颗树上要掉苹果,这个牛可以瞬间从一棵树到达另一棵树下面,但是这种瞬移技能只能释放最多w(30)次 。问你这个牛最多可以吃到多少苹果。(注:牛一开始在1号树下)ps:要是问西瓜就好了,因为西瓜不长在树上···· 

思路:

设a[i][j][k]表示这个牛在第i个苹果掉下来时,在j号树下,用了k次技能,所能得到的最多的苹果数。

递推公式:a[i][j][k]=max(a[i-1][j][k],a[i-1][!j][k-1]); if(v[i]==j)a[i][j][k]++;
边界条件:a[1][j][k];a[i][j][0];

关于递推公式以及边界条件的解释:

这个牛在第i个苹果掉下来的时候,在第j号树下,用了k次技能。能得到这个状态的上一状态为:这个牛在第i-1个苹果掉下来的时候,在第!j号树下,用了k-1次技能;或者这个牛在第i-1个苹果掉下来的时候,在第j号树下,用了k次技能。(关键也就是这个牛在第i-1个苹果掉下来和第i个苹果掉下来之间,有没有使用技能)然后如果,这个苹果他接到了,就+1呗~

然后是关于边界条件,很适合想想一个三维的表格来储存数组a(虽然想画个三维图,但是用笔画的图烂的掉渣,估计大家也看不清,就自己想象吧),这样的话,如果要推出第i层的一个,就需要知道第i-1层的两个格(沿i轴-1的一个,以及同i-1平面内无相交边的另一个)。这样,在i取1的时候,就找不到对应的i-1平面了,所以要确定边界a[1][j][k];同样,在k=0时就找不到对应的k-1了,所以也要确定边界a[i][j][0]。另外十分要注意,开始的时候在1号树下面,所以一切在2号数下面翻转0次得到的苹果数都是-inf。 


然后三层循环为什么从外到内的顺序为ikj:
还是有些疑问,不过目前对于这道题来看,调换ik的内外层关系并没有发生错误。对于三维图来说,只不过是改变了各个格的数值确定的顺序。然后就是对递推公式理解上就不太好解释了(其实也是可以解释的):一个一个的用技能,在第i个格用技能得到的总金额可以根据在第i-1个格用技能(a[i-1][j][k])或者不用这个技能(a[i-1][!j][k-1]) 两种情况来确定。


#include
     
     
      
      
#include
      
      
       
       
#define N 1050
#define W 40
#define inf 0x3f3f3f3f
using namespace std;

int n;
int w;
bool t[N]={0};
int a[N][2][W]={0};

void input()
{
	cin>>n>>w;
	for(int i=1;i<=n;i++)
	{
		int x;
		scanf("%d",&x);
		if(x==2)t[i]=1;
	}
}

void init()
{
	int s=0;
	a[0][1][0]=-inf; 
	for(int i=1;i<=n;i++)//确定a[i][j][0]
	{
		if(t[i]==0)
		{
			s++;
			a[i][0][0]=s;
		}
		a[i][1][0]=-inf; //开始的时候在1号树下面,所以一切在2号数下面翻转0次得到的苹果数都是-inf 
	}
	
	for(int k=1;k<=w;k++)//确定a[1][j][k]
	{
		for(int j=0;j<=1;j++)
		{
			if(t[1]==j)
			{
				a[1][j][k]=1;
			}
		}
	}	
}

void dp()
{
	init();//确定边界条件 
	for(int i=2;i<=n;i++)
	{
		for(int k=1;k<=w;k++)
		{
			for(int j=0;j<=1;j++)
			{
				a[i][j][k]=max(a[i-1][j][k],a[i-1][!j][k-1]);
				if(t[i]==j)
				{
					a[i][j][k]++;
				}
			}
		}
	}
}

int find()
{
	int max=-inf;
	for(int i=0;i<=1;i++)
	{
		for(int j=0;j<=w;j++)
		{
			if(max
       
        
 


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值