码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 4293 Groups(区间dp)

时间:2015-07-27 23:01:23      阅读:133      评论:0      收藏:0      [点我收藏+]

标签:dp   动态规划   acm   

HDU 4293

题意:有 n 个人,可任意分成若干组,然后每个人各提供一个信息,表示他们组前面有多少个人,后面有多少个人。问最多有多少个信息是真实的的。

思路:

这道题一开始给我的印象是什么乱七八糟的东西,后来也没想通到底该怎么做,好在赛后百度在手天下我有:)

我们可以把 这n个人看成一段区间 [1,n]。
设每个人的信息是a、b,则这个信息代表了他们组所在的区间 [a+1,n-b]。

若a+b>n,显然撒谎,跳过不做处理。

我们用一个Map[i][j]数组将同在一区间[i,j]的人数纪录下来,纪录过程中若Map[i][j] > n-i-j则说明提供[i,j]区间消息的人里有人撒谎,略过不计,令Map[i][j] = n-i-j;

问题转化成了在 [1,n] 这段区间中分布的若干个带有权值的区间,问如何选取一些不相交的区间,使权值之和最大。

我们用dp[i]表示[1,i]区间权值之和的最大值,转移方程为dp[i] = max(dp[i],dp[j]+map[j][i]).


code:

/*
* @author Novicer
* language : C++/C
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
#define INF 2147483647
#define cls(x) memset(x,0,sizeof(x))
#define rise(i,a,b) for(int i = a ; i <= b ; i++)
using namespace std;
const double eps(1e-8);
typedef long long lint;

const int maxn = 500 + 5;

int Map[maxn][maxn];
int dp[maxn];

int main(){
//	freopen("input.txt","r",stdin);
	int n;
	while(cin >> n){
		cls(Map);
		for(int i = 1 ; i <= n ; i++){
			int a,b;
			scanf("%d%d",&a,&b);
			if(a+b >= n)
				continue;
			else{
				if(n-a-b > Map[a+1][n-b])
					Map[a+1][n-b]++;
				else 
					Map[a+1][n-b] = n-a-b;
			}
		}
		cls(dp);
		for(int i = 1 ; i <= n ; i++)
			for(int j = 1 ; j <= i ; j++)
				dp[i] = max(dp[i] , dp[j-1]+Map[j][i]);
		cout << dp[n] << endl;
	}
		
	return 0;
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU 4293 Groups(区间dp)

标签:dp   动态规划   acm   

原文地址:http://blog.csdn.net/qq_15714857/article/details/47091951

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!