P1464 Function —— 洛谷
题源:P1464 Function - 洛谷
第一种解法:使用循环
这是我想到的第一个解法,纯暴力。
主要是因为条件的设置,规定三个数中有任意一个数超过20,就指需要计算20就行。所以我就想到了使用三重循环,时间复杂度最坏也只有O(20 ^ 3)(一次输入时)。
AC代码:
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
long long res;
long long f[25][25][25];
int main()
{
long long int a,b,c;
scanf("%lld%lld%lld",&a,&b,&c);
long long a1,b1,c1;
while(a != (long long)-1 || b != (long long)-1 || c != (long long)-1)
{
a1 = a,b1 = b,c1 = c;
if(a <= 0 || b <= 0 || c <= 0) {
printf("w(%lld, %lld, %lld) = 1\n",a1,b1,c1);
}
else
{
if(a > 20 || b > 20 ||c > 20) a = 20,b = 20,c = 20;
for(int i = 0;i <= 20;i++)
{
for(int j = 0;j <= 20;j++)
{
f[i][j][0] = 1;
f[i][0][j] = 1;
f[0][i][j] = 1;
f[0][0][j] = 1;
f[0][j][0] = 1;
f[j][0][0] = 1;
f[0][0][0] = 1;
}
}
for(int i = 1;i <= a;i++)
{
for(int j = 1;j <= b;j++)
{
for(int k = 1;k <= c;k++)
{
if(f[i][j][k] != 0) continue;
if(a < b && b < c)
{
f[i][j][k] = f[i][j][k - 1] + f[i][j - 1][k - 1] - f[i][j - 1][k];
}
else {
f[i][j][k] = f[i - 1][j][k] + f[i - 1][j - 1][k] + f[i - 1][j][k - 1] - f[i - 1][j - 1][k - 1];
}
}
}
}
printf("w(%lld, %lld, %lld) = %lld\n",a1,b1,c1,f[a][b][c]);
}
scanf("%lld%lld%lld",&a,&b,&c);
}
return 0;
}
第二种解法:记忆化搜索
因为题目的算法标签好歹有一个搜索,所以我觉得不使用搜索的话,好像也是白做。
所以就看了题解。
记忆化搜索简介:
记忆化搜索是一种通过存储已经遍历过的状态西信息,避免对同一状态重复遍历的算法。
它是动态规划的一种实现方式,在记忆化搜索中,当算法计算到某个子问题的结果时,首先检查是否已经计算过该问题。如果已经计算过,则直接返回已经存储的结果;否则,计算该问题,并将结果存储下来以备将来使用。
所以,在这道题中,我们可以把每一个“w”函数的值储存起来,下一次就可以直接调用,节省大量时间。
AC代码:
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
typedef long long LL;
LL dp[25][25][25];
LL w(LL a,LL b,LL c)
{
if(a <= 0 || b <= 0 || c <= 0) return (LL)1;
if(a > 20 || b > 20 || c > 20 ) return w(20,20,20);
if(a < b && b < c){
if(dp[a][b][c - 1] == 0)
{
dp[a][b][c - 1] = w(a,b,c - 1);
}
if(dp[a][b - 1][c - 1] == 0)
{
dp[a][b - 1][c - 1] = w(a,b - 1,c - 1);
}
if(dp[a][b - 1][c] == 0)
{
dp[a][b - 1][c] = w(a,b - 1,c);
}
dp[a][b][c] = dp[a][b][c - 1] + dp[a][b - 1][c - 1] - dp[a][b - 1][c];
}
else {
if(dp[a - 1][b][c] == 0)
{
dp[a - 1][b][c] = w(a - 1,b,c);
}
if(dp[a - 1][b - 1][c] == 0)
{
dp[a - 1][b - 1][c] = w(a - 1,b - 1,c);
}
if(dp[a - 1][b][c - 1] == 0)
{
dp[a - 1][b][c - 1] = w(a - 1,b,c - 1);
}
if(dp[a - 1][b - 1][c - 1] == 0)
{
dp[a - 1][b - 1][c - 1] = w(a - 1,b - 1,c - 1);
}
dp[a][b][c] = dp[a - 1][b][c] + dp[a - 1][b - 1][c] + dp[a - 1][b][c - 1] - dp[a - 1][b - 1][c - 1];
}
return dp[a][b][c];
}
int main()
{
LL a, b,c;
LL res = 0;
while(scanf("%lld %lld %lld",&a,&b,&c))
{
if(a == -1 && b == -1 && c == -1) break;
res = w(a,b,c);
printf("w(%lld, %lld, %lld) = %lld\n",a,b,c,res);
}
}