0
点赞
收藏
分享

微信扫一扫

The 37th ACM/ICPC Asia Regional ChengDu Site Online Contest - F Groups


     成都这场状态不对...没有做进现场..不过还好天津能去了...期待这周末浙江两连发给力...

     本题是一个DP问题...状态的表示:    把所有人看成一个直线...其中有些人可能被括在一起...dp[ k ] 代表到达第 k 个人时最多诚实人数...

     做个预处理...将A,B相同的人合并为一个Group...我是用的并查集...这里要注意一点...这个集合的人数不能超过n-A-B...所以取个人数与n-A-B的较小值作为这个Group的人数...那么此时得到的就是一个个Group..每个Group的信息有: 共同的A,B..以及人数num...  为了dp的层次..将所有Group按A从小到大排序...

      dp转移是n^2的..当更新一个Group时..找出dp[1~A]的最大值+Group合法人数判断更新到dp[B]....(一个人若说谎可以任意的调整他...那么可以填补中间的空隙)

      dp[1~n]的最大值既是解了....


Program:

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<map>
#include<queue>
#include<stack>
#define ll long long
#define oo 1000000000
#define pi acos(-1)
using namespace std;
struct node
{
int A,B,num,father;
}p[505];
int n,m,dp[505];
int getfather(int k)
{
if (p[k].father==k) return k;
return p[k].father=getfather(p[k].father);
}
bool cmp(node a,node b)
{
if (a.A!=b.A) return a.A<b.A;
return a.B<b.B;
}
int main()
{
int i,j,x,y,k,ans;
while (~scanf("%d",&n))
{
for (i=1;i<=n;i++)
{
scanf("%d%d",&p[i].A,&p[i].B);
p[i].father=i;
p[i].num=1;
}
for (i=1;i<n;i++)
for (j=i+1;j<=n;j++)
if (p[i].A==p[j].A && p[i].B==p[j].B)
{
x=getfather(i);
y=getfather(j);
if (x!=y)
{
p[y].num+=p[x].num;
p[x].father=y;
}
}
m=0;
for (i=1;i<=n;i++)
if (p[i].father==i && p[i].A+p[i].B<n)
{
m++;
p[m].A=p[i].A; p[m].B=p[i].B;
p[m].num=min(n-p[i].A-p[i].B,p[i].num);
}
sort(p+1,p+1+m,cmp);
memset(dp,0,sizeof(dp));
ans=0;
for (k=1;k<=m;k++)
{
x=0;
for (i=0;i<=p[k].A;i++) x=max(x,dp[i]);
dp[n-p[k].B]=max(dp[n-p[k].B],x+p[k].num);
ans=max(dp[n-p[k].B],ans);
}
printf("%d\n",ans);
}
return 0;
}


Program: (2013_8_12)

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<string.h>
#define ll long long
#define oo 1000000007
#define pi acos(-1.0)
#define MAXN 505
using namespace std;
struct node
{
int L,R,num;
}S[MAXN];
int g[MAXN][MAXN],dp[MAXN];
bool cmp(node a,node b) { return a.L<b.L; }
int main()
{
int n,i,j,m,ans;
while (~scanf("%d",&n))
{
memset(S,0,sizeof(S));
memset(g,0,sizeof(g));
m=0;
for (i=1;i<=n;i++)
{
int l,r;
scanf("%d%d",&l,&r);
if (l+r>=n) continue;
if (!g[l][r]) g[l][r]=++m,S[m].L=l,S[m].R=r;
S[g[l][r]].num++;
}
for (i=1;i<=m;i++) S[i].num=min(S[i].num,n-S[i].L-S[i].R),S[i].R=n-S[i].R;
sort(S+1,S+1+m,cmp);
ans=0;
memset(dp,0,sizeof(dp));
for (i=1;i<=m;i++)
{
for (j=0;j<=S[i].L;j++)
dp[S[i].R]=max(dp[S[i].R],dp[j]+S[i].num);
ans=max(ans,dp[S[i].R]);
}
printf("%d\n",ans);
}
return 0;
}





举报

相关推荐

0 条评论