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

hdu_1069_Monkey and Banana hdu_1078_FatMouse and Cheese poj_1836_Alignment

时间:2014-11-02 09:20:16      阅读:223      评论:0      收藏:0      [点我收藏+]

标签:dp   poj   hdu   

hdu_1069_Monkey and Banana

http://acm.hdu.edu.cn/showproblem.php?pid=1069

天花板上挂着一些香蕉,Monkey想要吃(Monkey不够高),于是Monkey想利用n个石块中的一些(长方体形状)堆起来,每层的石块的长和宽都要比前面一层的小(不可相等),这样Monkey才能爬上去,石块不限量。

考虑到石块可以转,所以每种石块有3种有效状态(如 10*20*30的石块,三种有效状态的长宽高分别是 30*20*10、30*10*20、20*10*30);由此也可以知道一种石块不可能使用超过3次。所以我们可以当做有3*n种不可转的石块。

首先进行排序,按长宽从大到小排序。

dp[i] 表示以第i种石块作为顶的最高可以有多高。我们要在前i-1种情况下找出能放下第i种石块的最高的情况。

dp[i]=max(dp[0...i-1]+s) //s为第i种石块的高。(==加了一个石块表示地面,即长宽等于INF,高为0,这样所有的石块都可以放置在这个”地面石块上面“)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define INF 100000000

struct Node {
	int x,y,z;
	void set (int X,int Y,int Z){
		x = X;
		y = Y;
		z = Z;
	}
};

bool cmp (Node a,Node b){
	if (a.x==b.x) return a.y>b.y;
	else return a.x>b.x;
}

int main(){
	int n;int c=1;
	while (cin>>n,n){
		int a[3];
		Node s[200];
		int dp[200];
		memset (dp,0,sizeof(dp));
		for (int i=0;i<n;i++){
			for (int j=0;j<3;j++)
				cin>>a[j];
			sort(a,a+3);
			s[i*3+0].set(a[2],a[1],a[0]);
			s[i*3+1].set(a[2],a[0],a[1]);
			s[i*3+2].set(a[1],a[0],a[2]);
		}
		s[n*3].set(INF,INF,0);
		sort (s,s+n*3+1,cmp);

		dp[0]=0;
		int t;
		for (int i=1;i<=3*n;i++){
			t=0;
			for (int j=i-1;j>=0;j--){
				if (s[j].x>s[i].x&&s[j].y>s[i].y){
					if (dp[t]<dp[j]){
						t=j;
					}
				}
			}
			dp[i]=dp[t]+s[i].z;
		}
		for (int i=1;i<=3*n;i++){
			dp[0]=max(dp[0],dp[i]);
		}
		cout<<"Case "<<c++<<": maximum height = "<<dp[0]<<endl;
	}
}

hdu_1078_FatMouse and Cheese

http://acm.hdu.edu.cn/showproblem.php?pid=1078

FatMouse 在一些存放了奶酪的”网格“里(位置<0,0>),因为外面有只猫,说以FatMouse每次最多只能走k步,当然,FatMouse可以往上下左右四个方向走。FatMouse每到一个网格就要吃掉网格里的奶酪,为了维持能量,FatMouse每次吃的奶酪都要比上一次吃的大。求FatMouse最多能吃多少奶酪。

看着像求一个最大和上升子序列,可是是二维的。wiking 说的把坐标存起来换成一维的。

结构体存奶酪大小和坐标(x,y),按奶酪大小排序,比(0,0)位置小的奶酪就不用理他了。

dp[i][j]表示以第[i][j]奶酪为最后吃的的最大值。dp[i][j]=max(dp[x][y]+a[i][j]);(dp[x][y]<a[i][j]) [x][y] 是可以走到ij的位置,有4个方向最多4*k个位置。

==这样我一直wa,因为即使a[i][j]>a[0][0],还是有可能没有(x,y)可以到达他的,不删除的话就会多一个起点。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

struct Node {
	int v,x,y;
};

bool cmp (Node a,Node b){
	return a.v<b.v;
}

int main (){
	int n,k;
	while (cin>>n>>k){
		if (n==-1&&k==-1){
			break;
		}
		int a[106][106],v=0;
		int dp[106][106];
		int use[106][106];
		memset(dp,0,sizeof(dp));
		memset(use,0,sizeof(use));
		Node s[10010];
		for (int i=0;i<n;i++){
			for (int j=0;j<n;j++){
				scanf ("%d",&a[i][j]);
				s[v].x=i;s[v].y=j;
				s[v].v=a[i][j];
				v++;
			}
		}
		int ans=a[0][0],i;
		// cout<<v<<endl;
		sort (s,s+v,cmp);
		for (i=0;i<v;i++){
			if (s[i].x==0&&s[i].y==0) {
				dp[0][0]=a[0][0];i++;
				break;
			}
			use[s[i].x][s[i].y]=1;
		}
		// cout<<s[i].x<<" "<<s[i].y<<endl;
		for (i;i<v;i++){
			int X,Y,maxn=-1;
			X=s[i].x;Y=s[i].y;
			for (int j=1;j<=k;j++){
				if (X+j<n&&a[X+j][Y]<s[i].v&&!use[X+j][Y]){
					maxn=max(maxn,dp[X+j][Y]);
				}
				if (Y-j>=0&&a[X][Y-j]<s[i].v&&!use[X][Y-j]){
					maxn=max(maxn,dp[X][Y-j]);
				}
				if (X-j>=0&&a[X-j][Y]<s[i].v&&!use[X-j][Y]){
					maxn=max(maxn,dp[X-j][Y]);
				}
				if (Y+j<n&&a[X][Y+j]<s[i].v&&!use[X][Y+j]){
					maxn=max(maxn,dp[X][Y+j]);
				}
			}//cout<<maxn<<endl;
			if (maxn==-1) use[X][Y]=1;
			dp[X][Y]=maxn+s[i].v;
			ans=max(ans,dp[X][Y]);
			// cout<<ans<<endl;
			//cout<<s[i].x<<" "<<s[i].y<<" "<<s[i].v<<" ";
		}
		cout<<ans<<endl;
	}
	return 0;
}

poj_1836_Alignment

http://poj.org/problem?id=1836

队长检查士兵,n个士兵们排队高矮不齐,队长希望提出几个士兵,使得队伍里的每个士兵左边或右边的士兵都比他矮。

从左往右求LIS dp0[i]表示已i为结尾的最长子序列长度。

从右往左求LIS dp1[j]表示已j为结尾的最长子序列长度。

然后枚举i和j求出最小的n-dp0[i]-dp1[j];注意dp0[n-1]和dp1[0]两种特殊情况。

<pre name="code" class="cpp">#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#ifndef INF
#define INF 1000000000
#endif

int n;

void solve (double a[],int dp[]){
	dp[0]=0;
	for (int i=0;i<n;i++){
		dp[i]=1;
		for (int j=0;j<i;j++){
			if (a[i]>a[j]){
				dp[i]=max(dp[i],dp[j]+1);
			}
		}
	}
}

void swapd (int dp[0]){
	for (int i=0;i<n/2;i++){
		swap(dp[i],dp[n-1-i]);
	}
}

int main(){
	double a[1010],b[1010];
	int dp0[1010],dp1[1010];
	memset(dp0,0,sizeof(dp0));
	cin>>n;
	for (int i=0;i<n;i++){
		cin>>a[i];
		b[n-1-i]=a[i];
	}
	solve(a,dp0);
	solve(b,dp1);
	swapd(dp1);
	/*for (int i=0;i<n;i++){
		printf ("%d ",dp0[i]);
	}printf ("\n");
	for (int i=0;i<n;i++){
		printf ("%d ",dp1[i]);
	}printf ("\n");
	cout<<endl;*/
	int ans=min(n-dp0[n-1],n-dp1[0]);
	for (int i=0;i<n-1;i++){
		for (int j=i+1;j<n;j++){
			ans=min(ans,n-dp0[i]-dp1[j]);
		}
	}
	cout<<ans<<endl;
	return 0;
}



dp总是水我这样好吗==


hdu_1069_Monkey and Banana hdu_1078_FatMouse and Cheese poj_1836_Alignment

标签:dp   poj   hdu   

原文地址:http://blog.csdn.net/xuelanghu407/article/details/40691925

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