您的位置:首页 > 其它

hrbust 2287 Bridge【最长上升子序列变形+dp最小花费】好题

2016-10-01 17:12 459 查看
Bridge
Time Limit: 1500 MSMemory Limit: 32768 K
Total Submit: 49(10 users)Total Accepted: 11(8 users)Rating: 







Special Judge: No
Description
Long long ago, there were two tribes called Radiant and Dire. In each tribe, there are many heroes who were aggressive that they wanted to fight with the heroes in the other tribe. Unfortunately, a river stopped their pace of attack. So the elders of the two tribes had a negotiation with each other. Finally, they decided to build some bridges. They gave the solutions of building bridges with the coordinate of different sides of the bridge and the cost of it. To prevent confusion, any of the two bridges could not cut across each other (except on the endpoints of the bridges). And they wanted to know how many bridges they could build at most, and under this condition, what is the minimum cost.
Input
The first line contains an integer T, indicating the total number of test cases (T<=10).
First line of each test case contains a number n(n<=10^4),means the number of bridges.
Then following n lines contains three integer xi, yi, vi (1<=xi, yi, vi<=10^4),means the coordinate of different sides
and the cost of it.It is guaranteed that there are no two bridges have the same xi and yi.
Output
For each test case, output one line containing "Case #t: a b", where t is the test case number (starting from 1), a is the maximum number of bridges, and b is the minimum cost of building the bridges.
Sample Input
1

3

3 1 3

1 2 2

4 5 6
Sample Output
Case #1: 2 8
Source
"尚学堂杯"哈尔滨理工大学第五届程序设计团队赛(正式)
题目大意:

给你N个点,每个点的坐标给你,并且给你建立这个点需要的花费。

问题转化了之后的描述:

建立的桥使其在二维坐标系下越来越高,问最多能够建立几个点,对应的最少花费是多少。

分析样例:

对应建立点1、3和点2、3都是使其越来越高的桥 ,对应花费为:9,8,所以输出是2 8。

思路:

1、首先,我们对所有点进行排序(先按照x从小到大排序,再按照y从小到大排序),那么对应我们要让建立起来的桥越来越高,其实也就是在求一个最长上升子序列。

2、对应最长上升子序列设定数组dp【i】,表示序列以i结尾的最长上升子序列能够建立的点的个数。那么对应状态转移方程:

dp【i】=max(dp【j】+1,dp【i】)【j<i&&点j比点i低(a[i].x>=a[j].x&&a[i].y>=a[j].y)】;

在dp过程中,维护一个最大len,表示整个序列的最长上升子序列的长度。len=max(dp【i】,len)

3、那么对应最小花费要如何处理呢?我们对应也设定一个dp数组:dpcost【i】表示序列以i结尾的最长上升子序列的最小花费。

那么其状态转移方程:

if(dp【j】+1>dp【i】)dpcost【i】=dpcost【j】+a【i】.w;

if(dp【j】+1==dp【i】&&dpcost【i】<dpcost【j】+a【i】.w)dpcost【i】=dpcost【j】+a【i】.w;

4、对应细节比较多,谨慎一点就可以了,具体内容参考代码

Ac代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
struct node
{
int x,y,w;
}a[100000];
int cmp(node a,node b)
{
if(a.x==b.x)
{
return a.y<b.y;
}
else return a.x<b.x;
}
int dp[10002];
int dpcost[100005];
int main()
{
int t;
int kase=0;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);
}
int len=0,ans=0;
sort(a,a+n,cmp);
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++)
{
dp[i]=1;
dpcost[i]=a[i].w;
for(int j=0;j<i;j++)
{
if(a[i].x>=a[j].x&&a[i].y>=a[j].y)
{
if(dp[j]+1>dp[i]||(dp[j]+1==dp[i]&&dpcost[j]+a[i].w<dpcost[i]))
{
dpcost[i]=dpcost[j]+a[i].w;
dp[i]=dp[j]+1;
}
}
}
if(dp[i]>len||(dp[i]==len&&dpcost[i]<ans))
{
len=dp[i];
ans=dpcost[i];
}
}
printf("Case #%d: %d %d\n",++kase,len,ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息