您的位置:首页 > 其它

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

2012-09-17 20:59 477 查看
成都这场状态不对...没有做进现场..不过还好天津能去了...期待这周末浙江两连发给力...

本题是一个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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐