1260. Nudnik Photographer dp

题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1260

描述:1,2,3,,,n.排成一排,第一个数必须是1,且相邻的两个数差的绝对值 <= 2.

思路:一开始没想出来递推式,(动态规划没怎么做过,碰到都是泪啊,该多练习了)。就用dfs写了一个程序求前面几十个(大概n=30左右时间就不能忍受了)

#include <iostream>
#include <cstdio>
#include <cstring>
int a[60], ans, vis[60], n;
void dfs(int pos)
{
	if (pos == n)
	{
		++ans;
		return;
	}
	else
	{
	 	for (int i = 2; i <= n; ++i)
		if (!vis[i] && abs(i - a[pos-1]) <= 2)
		{
			vis[i] = 1;
			a[pos] = i;
			dfs(pos+1);
			vis[i] = 0;
		}
    }
}
int main()
{
	while (scanf("%d", &n) != EOF)
	{
		memset(vis, 0, sizeof(vis));
		ans = 0;
		for (int i = 0; i < n; ++i)
			a[i] = i + 1;
		dfs(1);
		printf("%d\n", ans);
	}
	system("pause");
	return 0;
}


求出来前面一些答案:

n  =   1 2 3 4 5 6 7   8    9    10   11  12   13
ans=   1 2 2 4 6 9 14  21   31   46   68  100  147

然后就发现了规律f[n] = f[n-1] + f[n-2] - f[n-5],后来看Discussion有人的数学公式是f[i] = f[i-1] + f[i-3] + 1,其实是一样的,递推一下就行了。

证明:

f[i] = f[i-1] + f[i-3] + 1
所以 f[i-2] = f[i-3] + f[i-5] + 1

所以:
f[i-2] - f[i-3] - f[i-5] = 1
带入f[i]得:
f[i] = f[i-1] + f[i-3] + f[i-2] - f[i-3] - f[i-5]  = f[i-1] + f[i-2] - f[i-5]。

先列个表:

n=1

1

n=2
1 2

n=3
1 2 3

........

1 3 2

n=4
1 2 3 4
1 2 4 3

...........

1 3 2 4

............

1 3 4 2

n=5
1 2 3 4 5
1 2 3 5 4
1 2 4 3 5
1 2 4 5 3

..............

1 3 2 4 5

..............

1 3 5 4 2
f[n]的构造方式有三种:(注意以上几组数据对于相同的n,虚线分割的数据是不同的构造方式)

(1) 2 放在 2nd 位置,有f[n-1]种

(2) 3 放在 2nd 位置, 2在 3rd 位置,此时 4 必须在 4th 位置。有f[n-3]种

(3) 最有还有 1 种按照1 3 5 .... 8 6 4 2 即奇增偶减的方式。

f[n] = f[n-1] + f[n-3] + 1

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PegasusWang_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值