HDU5526/BestCoder Round #61 (div.1)1004 Lie 背包DP

Lie

 
 
问题描述
一个年级总共有N个学生,每个人属于唯一一个班级。现在他们站在一排,同班同学并不一定会站在一起,但每个人都会说一句话:“站在我左边的有Ai个同班同学,右边有Bi个同班同学”。然而并不是每个人都会说真话,老师也忘了他们说话的顺序,现在老师想知道最多有多少人的话同时不矛盾。
输入描述
输入有多组数据,不超过100组.
每组数据第一行包含一个整数N.(1leq Nleq 1000 )(1N1000)
随后N行,每行包含两个数字Ai和Bi.(0leq Ai,Bileq 1000 )(0Ai,Bi1000)
输出描述
对于每组数据输出一行答案.
输入样例
3
0 2
2 0
3 0
5
0 0
1 0
0 0
0 0
0 0
输出样例
2
4
 
 

题解:根据左右边同班同学的人数可以得知其班级人数和其在班上相对位置,只有班级人数相同才可能为同一个班级,而在同一个班级的人出现矛盾的只能是班上相对位置相同。先根据班级人数排序,对于班级人数相同的统计每个相对位置上有多少人,枚举人数为x的班级有y个,当y确定的时候就可以贪心得出最大不矛盾数量。这就转化成了分组背包,最后使得挑选出来的年级人数不超过N即可。复杂度O({n}^{2})O(n2​​).

///1085422276
#include<bits/stdc++.h>
using namespace std ;
typedef long long ll;
#define mem(a) memset(a,0,sizeof(a))
inline ll read()
{
    ll x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
//****************************************
#define maxn 1999+5
#define mod 1000000007
struct ss{
  int l,r,s;
}a[maxn];
int cmp(ss s1,ss s2){
return s1.s<s2.s;
}int n,H[maxn];
vector<int >G[maxn],A;
int V[maxn];
vector< pair<int ,int > >ans;
int main()
{
       while(scanf("%d",&n)!=EOF){mem(V);
        for(int i=1;i<=n;i++){
            scanf("%d%d",&a[i].l,&a[i].r);
            a[i].s=a[i].l+a[i].r+1;
       }int k=0;
       for(int i=0;i<=1000;i++)G[i].clear();
       A.clear();ans.clear();
       sort(a+1,a+n+1,cmp);
       for(int i=1;i<=n;i++){
         G[a[i].s].push_back(a[i].l+1);
         if(!V[a[i].s])
         A.push_back(a[i].s);V[a[i].s]=1;
       }mem(H);
       for(int i=0;i<A.size();i++){int maxx=0;
         for(int j=0;j<G[A[i]].size();j++){
            H[G[A[i]][j]]++;maxx=max(maxx,H[G[A[i]][j]]);
         }
         while(maxx){
            int ab=0;
          for(int j=1;j<=A[i];j++){
            if(H[j]) ab++,H[j]--;
          } 
          ans.push_back(make_pair(A[i],ab));
          maxx--;
         }
       }int dp[maxn];mem(dp);
       for(int i=0;i<ans.size();i++){
        for(int j=n;j>=ans[i].first;j--){
            dp[j]=max(dp[j],dp[j-ans[i].first]+ans[i].second);
        }
       }
       cout<<dp[n]<<endl;
       }
    return 0;
}
31ms
原文地址:https://www.cnblogs.com/zxhl/p/4944059.html