您的位置:首页 > 其它

soj 2800 三角形(DP)

2015-10-28 16:22 288 查看
题意

给你一个大三角形,黑色的是被减去的,白色的是剩下的,问剩下的白色区域中,最大的倒三角形是?

分析:

看到这个题,首先想一下暴力,恩..可以搞,稳定超时.

然后我们需要去找如何DP了么…

那么是不是可以用直观的记忆化搜索呢?….想了一下,好像并不是很直观…

只有强行dp了么,找一找把当前的问题,分解为前面一个阶段的多个状态的子问题决定的.

那么我们定义以点(i,j)为顶点的倒三角形的最大面积为dp[i][j]吧,这可以分解么??

貌似可以分解为它上面左右两边的两个倒三角形来做啊…

这样取其上边两个倒三角形中较小的一个的面积的2倍,减去中间重叠的部分,加上多出的两个顶点即可,求出dp[i][j],有转移方程:dp[i][j]=min(dp[i−1][j−1],dp[i−1][j+1])+2−k;

其中k为中间的重叠部分,可有左右两边较小上交有的高减一的平方算出.(本题中高平方即为三角形面积).

但是感觉..这样写在好难看的样子,好吧也能ac就这样了吧……

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
using namespace std;
const int mod = 1e9 + 9, maxn = 2e3 +9, INF = 0x3fffffff;
typedef long long  ll;
int n, dp[maxn][maxn];
char g[maxn][maxn];
#define max(x, y) (x) > (y) ? (x) : (y)
#define min(x, y) (x) < (y) ? (x) : (y)

int main(void) {
while (true) {
scanf("%d", &n);
if (!n) break;
for (int i = 0; i <= n + 1; i++) {
for (int j = i - 1; j <= 2 * n - i + 1; j++) {
g[i][j] = 'X';
}
}
for (int i = 1; i <= n; i++) {
for (int j = i; j <= 2 * n - i; j++) {
char c = getchar();
if (c != 'X' && c != 'O') {
j--;
continue;
}
g[i][j] = c;
dp[i][j] = g[i][j] == 'O' && j % 2 == i % 2 ? 1 : 0;
}
}
int ans = -INF;
for (int i = 1; i <= n; i++) {
for (int j = i; j <= 2 * n - i; j++) {
ans = max(ans, dp[i][j]);
if (g[i][j] != 'O') continue;
if (j % 2 == i % 2) {
if (g[i - 1][j] == 'O' && g[i - 1][j - 1] == 'O' && g[i - 1][j + 1] == 'O') {
int k = min(dp[i - 1][j - 1], dp[i - 1][j + 1]);
dp[i][j] = k * 2 + 2 - (int(sqrt(double(k)) + 0.4) - 1) * (int(sqrt(double(k)) + 0.4) - 1);
}
}
ans = max(ans, dp[i][j]);
}
}

printf("%d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: