bzoj2298 problem a 动态规划

    题目等价于求最多多少个人说真话(答案忘记用n减Wa了两发。。)。根据每个人的ai,bi,我们可以得到他的名词的区间(如果他说真话)[ai+1,n-bi],同时ai+1...n-bi的人的分数相同。那么我们设f[i]表示当i与i+1分数不同时,名词比i前面或=i的最多有几个人不冲突。那么,

    f[i]=max{f[i-1],f[j]+min(i-j+1,区间为[i+1,j]的人数)},最后n-f[n]即答案。

AC代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 100005
using namespace std;

int n,cnt,dp[N]; struct node{ int l,r; }a[N];
bool cmp(node aa,node bb){ return (aa.r==bb.r)?aa.l<bb.l:aa.r<bb.r; }
int main(){
	scanf("%d",&n); int i,j=1;
	for (i=1; i<=n; i++){
		int x,y; scanf("%d%d",&x,&y);
		if (x+y<n){ a[++cnt].l=x+1; a[cnt].r=n-y; }
	}
	sort(a+1,a+cnt+1,cmp);
	for (i=1; i<=n; i++){
		dp[i]=dp[i-1]; while (a[j].r<i) j++; int tmp=0;
		for (; a[j].r==i; j++){
			if (a[j].l==a[j-1].l) tmp++; else tmp=1;
			dp[i]=max(dp[i],dp[a[j].l-1]+min(tmp,i-a[j].l+1));
		}
	}
	printf("%d\n",n-dp[n]);
	return 0;
}

by lych

2016.2.11

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值