uva 1543 Telescope

终于找到一点自信,没有看别人题解ac这道lrj紫书上的题目,一旦想到用海伦公式其他的就很简单了,我发现用递归写dp,真的比循环写dp要容易些。主要思路就是dfs函数中的循环语句。其实这道题目也可以看做搜索类的题目,状态转移方程式是dp[i][j][n]表示在i,j点中取n个节点的最大面积(i,j必取),dp[i][j][n] = max(dp[k][j][n-1]+area[i][k][j]) 其中i+1<= k <= j-1.就是这样简单的思路,有点想石子合并中一些思路。

题目链接:https://vjudge.net/problem/UVA-1543

#include 
#include 
#include 
#include 

using namespace std;

const double pi = 3.14159265358979323846;
const int maxn = 60;
int n , m;
double point[maxn];
double area[maxn][maxn][maxn];
double dp[maxn][maxn][maxn];

double getangle (int i , int j) {
	double tmp = abs(point[i]-point[j]);
	return tmp > 0.5 ? 1-tmp : tmp;
}

double getarea (int i , int j , int k) {
	double aij = getangle(i,j)*pi , ajk = getangle(j,k)*pi , aki = getangle(k,i)*pi;
	double eij = sin(aij)*2 , ejk = sin(ajk)*2 , eki = sin(aki)*2;
	double p = (eij+ejk+eki)/2;
	return sqrt(p*(p-eij)*(p-ejk)*(p-eki));
}

void initarea () {
	for (int i = 1 ; i <= n ; i++)
		for (int j = i+1 ; j <= n ; j++)
			for (int k = j+1 ; k <= n ; k++) area[i][j][k] = getarea(i, j, k);
}

double dfs (int i , int j , int n) {
	double ans = 0;
	if (dp[i][j][n]) return dp[i][j][n];
	if (n == 0) return 0; 
	for (int k = i+1 ; k <= j-1 ; k++)
		if (j-k > n-1) ans = max(ans , dfs(k, j, n-1)+area[i][k][j]);
	return dp[i][j][n] = ans; 
}

int main () {
	while (scanf("%d%d" , &n , &m) != EOF && n && m) {
		memset(area,0,sizeof(area));
		memset(dp,0,sizeof(dp));
		memset(point,0,sizeof(point));
		double ans = 0;
		for (int i = 1 ; i <= n ; i++) scanf("%lf" , &point[i]);
		initarea();
		for (int i = 1 ; i <= n ; i++)
			for (int j = i+m-1 ; j <= n ; j++) ans = max(ans , dfs(i,j,m-2)); 
		printf ("%.6lf\n" , ans);
	}
}


你可能感兴趣的:(动态规划)