10.鸣人的影分身
题目链接:http://noi.openjudge.cn/ch0206/8467/
本质就是放苹果,这类题用递归比较好想,就不用动规再费心了。
int fun(int m, int n)
{
if (m == 0 || n == 1)
return 1;
if (m < n)
return fun(m, m);
else
return fun(m - n, n) + fun(m, n - 1);
}
int main()
{
int t;
int m, n;
cin >> t;
while (t--)
{
cin >> m >> n;
cout << fun(m, n) << endl;
}
return 0;
}
11.乘积最大
又是一道挺经典的动规题,属于保存前i个状态求i+1状态的类型
#include<cstdio>
#include<cstring>
using namespace std;
int a[110];
int f[110][101]; //f[i][j]表示前i个数字划分成j个的最大乘积
int d[110][110];//d[i][j]表示第i位到第j位的数字
char st[110];
int main()
{
int n, m, k, i, j, x, y;
scanf("%d%d", &n, &m);
m++;
scanf("%s", st + 1);
for (i = 1; i <= n; i++)
a[i] = st[i] - '0';
for (i = 1; i <= n; i++)
{
d[i][i] = a[i];
for (j = i + 1; j <= n; j++)
d[i][j] = d[i][j - 1] * 10 + a[j];
}
for (i = 1; i <= n; i++)
f[i][1] = d[1][i];
for (k = 2; k <= m; k++)
{
for (i = k; i <= n; i++)
{
f[i][k] = 0;
for (j = i; j >= k; j--)
//状态转移方程
if (f[i][k] < d[j][i] * f[j - 1][k - 1])
{
f[i][k] = d[j][i] * f[j - 1][k - 1];
}
}
}
printf("%d\n", f[n][m]);
return 0;
}
题目链接:http://noi.openjudge.cn/ch0206/8787/
放苹果类题,只是不允许有空盘子,那就先给每个盘子里放个苹果即可,高中生必备知识....
13.切割回文
题目链接:http://noi.openjudge.cn/ch0206/8471/
还是经典动规题,知道前i个状态求i+1个状态
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
int t, f[1005], len;
char s[1005];
//判断从l到r是不是回文串
inline bool ok(int l, int r)
{
int lo = r - l + 1;
for (int i = l; i <= (l + r) / 2; ++i)
if (s[i] != s[r - (i - l + 1) + 1])
return false;
return true;
}
int main()
{
scanf("%d\n", &t);
while (t--)
{
cin >> s;
len = strlen(s);
for (int i = len; i >= 1; --i)
s[i] = s[i - 1];
//给f初始化,让每个值都很大
memset(f, 127 / 3, sizeof(f));
for (int i = 1; i <= len; ++i)
if (ok(1, i))
{
f[i] = 0;
continue;
}
else
//最精彩处,状态转移方程
for (int j = 1; j < i; ++j)
if (ok(j + 1, i))
f[i] = min(f[j] + 1, f[i]);
printf("%d\n", f[len]);
}
return 0;
}