作为一个刚学DP 的蒟蒻, 能避开DP 就想用点其他方法,于是头铁地写了个十分暴力的DFS ,属于是 明知TLE,偏向虎山行 了
#include <bits/stdc++.h>
using namespace std;
long long sum,n;
void dfs(int x, int y)
{
if((x+y)==n) {sum++;return;}
for(int i = y + 1; x + y + i <= n; i ++)
{
dfs(x + y, i);
}
return;
}
int main()
{
cin >> n;
for(int i = 1; i < n; i ++)
{
dfs(0,i);
}
cout << sum;
return 0;
}
![](https://img-blog.csdnimg.cn/3a20ef99de9a49e78697c7fa0a527904.png)
正合我意。。。
老老实实写DP。。
看到测试数据可以想到这题会爆int
用一个二维状态f [ i ] [ j ] 来表示 总共跑了 i 圈, 且以 j 圈来结尾 这个状态存的是有多少种跑法
这个状态转移方程还是比较好想的:
f [ i ] [ j ] += f [ i - j ] [ k ]
既然是以 j 圈结尾的,那么在你跑 j 圈之前,让你跑 i - j 圈且不限制以多少圈来结尾你有多少种跑法就等同于以 j 结尾总共跑 i 圈有多少种跑法
所以k就是以多少圈来结尾 把k从小到大遍历 要注意限制条件 k是必须小于 i - j 且小于 j 的 因为k作为倒数第二次跑的圈数 不仅要比总圈数小,还要比下一次也就是最后一次跑的圈数小
但是在判断条件里又得写小于等于 为什么呢
因为我们将f [ i ] [ i ] 初始化成 1 虽然题目要求不能一次性跑完 但为了状态的计算允许一次性跑完
不然算不了了
#include <bits/stdc++.h>
using namespace std;
long long f[505][505];
int n;
long long sum;
int main()
{
cin >> n;
for(int i = 1; i <= n; i ++)
{
f[i][i] = 1; //反其道而行之
for(int j = 1; j <= n; j ++)
{
for(int k = 1; k <= i - j && k < j; k ++)
if(i - j > 0) f[i][j] += f[i - j][k];
}
}
for(int i = 1; i < n; i ++)
{
sum += f[n][i];
}
cout << sum;
return 0;
}