标签:
一个年级总共有N个学生,每个人属于唯一一个班级。现在他们站在一排,同班同学并不一定会站在一起,但每个人都会说一句话:“站在我左边的有Ai个同班同学,右边有Bi个同班同学”。然而并不是每个人都会说真话,老师也忘了他们说话的顺序,现在老师想知道最多有多少人的话同时不矛盾。
输入有多组数据,不超过100组.
每组数据第一行包含一个整数N.(1\leq N\leq 1000 )(1≤N≤1000)
随后N行,每行包含两个数字Ai和Bi.(0\leq Ai,Bi\leq 1000 )(0≤Ai,Bi≤1000)
对于每组数据输出一行答案.
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(n?2??).
///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; }
HDU5526/BestCoder Round #61 (div.1)1004 Lie 背包DP
标签:
原文地址:http://www.cnblogs.com/zxhl/p/4944059.html