一、阿克曼函数
1. 审题
现在有函数
Ack
(
m
,
n
)
\text{Ack}(m,n)
Ack(m,n):
Ack
(
m
,
n
)
=
{
n
+
1
m
=
0
Ack
(
m
−
1
,
1
)
n
=
0
Ack
(
m
−
1
,
Ack
(
m
,
n
−
1
)
)
m
,
n
>
0
\text{Ack}(m,n) = \begin{cases} n+1 & m=0\\ \text{Ack}(m-1,1) & n=0 \\ \text{Ack}(m-1,\text{Ack}(m,n-1)) & m,n>0 \end{cases}
Ack(m,n)=⎩
⎨
⎧n+1Ack(m−1,1)Ack(m−1,Ack(m,n−1))m=0n=0m,n>0
给定非负整数
m
m
m(
m
≤
3
m\le 3
m≤3)和
n
n
n(
n
≤
12
n\le12
n≤12),求
Ack
(
m
,
n
)
\text{Ack}(m,n)
Ack(m,n)。
2. 参考答案
#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
ll m, n;
ll a[5][10000005]; // 因为有Ack(m-1, Ack(m, n-1))所有空间开得要很大
ll Ack(ll m, ll n)
{
if (m == 0) return n+1;
if (n == 0) return Ack(m-1, 1);
if (a[m][n] != 0) return a[m][n];
return a[m][n]=Ack(m-1, Ack(m, n-1));
}
int main()
{
freopen("ack.in", "r", stdin);
freopen("ack.out", "w", stdout);
cin >> m >> n;
cout << Ack(m, n);
fclose(stdin);
fclose(stdout);
return 0;
}
二、金币
1. 审题
在一个古老的迷宫中,有 n × m n\times m n×m 的房间,每个房间中都有一定数量的金币。现在有一个冒险家,他想从迷宫的左上角出发,到达右下角的出口,每一步只能向下或向右走一格,并且不能重复经过已经走过的房间,也不能走出迷宫的边界。冒险家在走过的每个房间都会拾取所有的金币,求他能拾取到的金币数量的最大值。
2. 参考答案
#include <iostream>
using namespace std;
int n, m;
int a[1005][1005];
int dp[1005][1005];
bool vis[1005][1005];
int dfs(int x, int y)
{
// 是否到达终点
if (x==n && y==m)
return a[x][y];
// 是否访问过
if (vis[x][y] && dp[x][y]!=0)
return dp[x][y];
vis[x][y] = 1; // 标记已被访问
// 向下/右走
int dcoin = 0, rcoin = 0;
if (x+1 <= n)
dcoin = dfs(x+1, y);
if (y+1 <= m)
rcoin = dfs(x, y+1);
return dp[x][y]=max(dcoin, rcoin)+a[x][y];
}
int main()
{
// 输入
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> a[i][j];
// 输出
cout << dfs(1, 1);
return 0;
}
三、消灭恶龙
1. 审题
镇上出现了一条史前魔龙,作为镇长的你想出了一个灭龙计划,需要组织不同的魔法师一起灭龙,每个魔法师使用的魔法都不一样,所以其魔法的威力也不一样,消耗的体力也不一样,所以需要出手次数需要尽可能的少,每个魔法师出手的次数不作限制,不一定每个魔法师都需要参与灭龙,已知魔龙的生命值为 M M M,一共有 N N N 名魔法师,并且已知 N N N 名魔法师对应魔法的威力值,作为镇长的你需要考虑最优的方案,使用尽可能少的出手次数来刚好击败魔龙。
2. 参考答案
#include <iostream>
#include <algorithm>
using namespace std;
int m, n;
int a[105];
int mincnt = 1e8;
bool cmp(int a, int b)
{
return a>b;
}
void dfs(int power, int cnt)
{
if (power == m)
{
mincnt = min(mincnt, cnt);
return;
}
if (power>m || cnt>=mincnt)
return;
for (int i = 1; i <= n; i++)
dfs(power+a[i], cnt+1);
}
int main()
{
// 输入
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i];
// dfs
sort(a+1, a+n+1, cmp);
dfs(0, 0);
// 输出
cout << ((mincnt==1e8)?-1:mincnt);
return 0;
}