3 2 0 0 2<span style="font-family: 'Courier New', Courier, monospace; white-space: pre-wrap;">2 2</span>32 00 22 2
法一:
用ri[i][j] 表示前i个人中,最后j个人为一组,被分在这个组的人数的个数 ri[i][j] <= j
用res[i]表示前i个人中说真话最多人数
res[i] = max(res[i], ri[i][j]+res[i-j])表示 前i个人中,最后j个人一组人数+前i-j个人说真话 中取最大值
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define maxn 501 int ri[maxn][maxn]; int res[maxn]; int main(){ int n,u,v,t; while(scanf("%d",&n)!=EOF){ memset(ri,0,sizeof(ri)); memset(res,0,sizeof(res)); for(int i = 0;i < n; i++){ scanf("%d%d",&u,&v); t = n-u-v; if(t<=0) continue; ri[u+t][t]++; ri[u+t][t] = min(ri[u+t][t],t); } int ans = 0; for(int i = 1;i <= n; i++){ for(int j = 1;j <= i; j++){ u = res[i-j]+ri[i][j]; if(u > res[i]) res[i] = u; } ans = max(ans,res[i]); } printf("%d\n",ans); } return 0; }
然后合并同类元素,转移的时候要 注意res[i] = max(res[i],res[i-1])即可,负责度nlogn但是数据太小了,跑不快~
#include<cstdio> #include<cstring> #include<algorithm> #include<map> using namespace std; #define maxn 501 struct Node{ int i,j,n; }; int comp(Node a,Node b){ if(a.i == b.i) return a.j < b.j; return a.i < b.i; } bool operator == (Node a,Node b){ return a.i == b.i && a.j == b.j; } Node queue[1007]; int res[maxn]; int main(){ int n,u,v,t; Node a; while(scanf("%d",&n)!=EOF){ memset(res,0,sizeof(res)); int cnt = 0,cnt1=0; for(int i = 0;i < n; i++){ scanf("%d%d",&u,&v); t = n-u-v; if(t<=0) continue; a.i = t+u, a.j = t, a.n = 1; queue[cnt++] = a; } sort(queue,queue+cnt,comp); for(int i = 1;i < cnt; i++){ if(queue[cnt1] == queue[i]) queue[cnt1].n+=queue[i].n; else queue[++cnt1] = queue[i]; } int ans = 0,t=0; for(int i = 0;i <= cnt1; i++){ a = queue[i]; while(t!=a.i)res[t+1] = max(res[t+1],res[t++]); res[a.i] = max(res[a.i],res[a.i-a.j]+min(a.j,a.n)); ans = max(ans,res[a.i]); } printf("%d\n",ans); } return 0; }