Description
Input
Output
Sample Input
3 2 0 0 2 2 2 3 2 0 0 2 2 2
Sample Output
2 2
Hint
The third player must be making a mistake, since only 3 plays exist.
题意:有n个人,可任意分成若干组,然后每个人个各提供一个信息,表示他们组前面有多少人,后面有多少人。问最多有多少个信息是不冲突的。
解:给n个人编号1到n,一个组报出前后有多少人时可以算出这组的人的区间,这样就可以把本题转化成给定一些带权值的区间,求不相交区间的最大权值。这样就可以先按区间排个序,然后依次更新就行了。
ac 代码:有一些解释
#include <iostream> #include <stdlib.h> #include <string.h> #include <stdio.h> #include <algorithm> using namespace std; const int maxn=600; struct node { int a,b; }d[maxn]; int dp[maxn],mp[maxn][maxn]; bool cmp(node x,node y) { if(x.b!=y.b) return x.b<y.b; return x.a<y.a; } int main() { int n; int a,b; while(scanf("%d",&n)!=-1) { for(int i=0;i<n;i++) { scanf("%d%d",&d[i].a,&d[i].b); d[i].a++; d[i].b=n-d[i].b; } sort(d,d+n,cmp); memset(mp,0,sizeof(mp));///mp[a][b]表示区间a到b有几个人 memset(dp,0,sizeof(dp)); for(int i=0;i<n;i++) { a=d[i].a,b=d[i].b; if(a>b||mp[a][b]>=b-a+1)///a>b肯定不行,这个然肯定撒谎了,mp[a][b]之间最多有b-a+1个人, continue; ///人满了就不需要再操作了 mp[a][b]++; dp[b]=max(dp[b],dp[a-1]+mp[a][b]);///dp[b]表示b之间有多少人没有撒谎 for(int j=b+1;j<=n;j++) dp[j]=dp[b]; } printf("%d\n",dp[n]); } return 0; }