题意:n个人组成m个小队,n个人每人反馈两个数A,B,表示这个人所在的小队前面有A个人,后面有B个人,经调查发现有某些人说了假话,求最多有多少人说真话。(n<=500)
分析题目可得,一个人给的数对A,B代表他的队伍区间为[A+1,n-B],由此可以开grp[i][j]和dp[i]两个数组。其中,grp[i][j]表示说自己的队伍区间为[i,j]的人数,dp[i]表示前i人中最多说真话的人数,显然方程为dp[i]=max{dp[j]+grp[j+1][i]} i∈[1,n],j∈[0,i)
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define M(a) memset(a,0,sizeof(a))
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
using namespace std;
int grp[503][503],dp[503];
//grp[i][j]表示说自己的队伍区间为[i,j]的人数
//dp[i]表示[1,i]中最多包含几个区间(即最多有几个人说真话)
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
M(dp);M(grp);
FOR(i,1,n)
{
int A,B;
scanf("%d%d",&A,&B);
if(grp[A+1][n-B]<n-B-A) //区间[A+1,n-B]的人数为n-A-B,说自己是[A+1,n-B]队伍中的人数grp[A+1][n-B]不超过n-A-B
grp[A+1][n-B]++;
}
FOR(i,1,n)
FOR(j,0,i-1)
dp[i]=max(dp[i],dp[j]+grp[j+1][i]);
printf("%d\n",dp[n]);
}
return 0;
}