關於動態規劃的理解

對於動態規劃的理解

從大二起,也做了不少的動態規劃題,但對於很多動態規劃狀態還是一知半解,究其原因,是在平時做題的過程中,不求甚解,遇到問題只是匆匆看看題解,而不深入探討。導致很多問題都模模糊糊的過去了,做題也等於沒有做。從現在開始正式的反思總結。新的一年,新的開始^_^

 1. ZOJ 1679  Telescope

  題意:這道題是給出一個圓,上面有n個點,從中選出m個點,選擇一種方案使得構成的m多邊形面積最大(m個點依次順序連接形成多邊形)。

題解:(動態規劃很多時候都需要枚舉子問題的狀態,從而推出所需問題的最優策略,這樣,對於子問題的枚舉策略就顯得至關重要。既然是枚舉,所有的情況都不能遺漏,枚舉條件的選取恰當與否決定了問題能否順利解決)這題的數據規模是40,因爲涉及到最大面積,考慮動態規劃,根據題意,猜測是區間DP,對於DP參數的設定:

dp(i, j, k) 表示以i開始,以j結束的擁有k個點的多邊形的最大面積,這昂最總答案是max{dp(i, j, m)}.

狀態轉移方程:dp(i, j, k) = max{ dp(i, j, k) , dp(i, q, k - 1) + Triangle(i, q, j) }.

代碼:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
#define N 50


int n, m;
double dp[N][N][N], _area[N][N][N];
struct Point{
	double x, y;
}P[N];

double cross(Point a, Point b, Point c)  
{  
    return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);  
}  

double area(Point a, Point b, Point c)  
{  
    return fabs(cross(a, b, c)/2.0);  
} 

void init(){
	for(int i = 0; i < n; i++)
		for(int j = 0; j < n; j++)
			for(int k = 0; k < n; k++){
					_area[i][j][k] = area(P[i], P[j], P[k]);
				}
	memset(dp, 0, sizeof dp);
}

void DP(){
	for(int i = 0; i < n; i++)
		for(int j = i + 2; j < n; j++)
			for(int k = 3; k <= m; k++)
				for(int q = i + k - 2 ; q < j; q++)
					dp[i][j][k] = max(dp[i][j][k], dp[i][q][k-1] + _area[i][j][q]);

	double ans = -INF;
	for(int i = 0; i < n; i++)
		for(int j = i + m - 1; j < n; j++){
			ans = max(ans, dp[i][j][m]);
		}
	printf("%.6lf\n", ans);
}

int main(){
	// freopen("2016.txt", "r", stdin);
	while(scanf("%d%d", &n, &m) && n + m){
		for(int i = 0; i < n; i++){
			double tmp;
			scanf("%lf", &tmp);
			tmp = 2 * PI * tmp;
			P[i].x = cos(tmp);
			P[i].y = sin(tmp);
		}
		init();
		DP();
	}
	return 0;
}




發佈了274 篇原創文章 · 獲贊 19 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章