hdu 4293 dp求最大权值不重合区间
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4293
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn = 506; int G[maxn][maxn]; int dp[maxn]; //dp[i]表示前i个人,最大有多少个人没撒谎。 int main() { //freopen("E:\\acm\\input.txt","r",stdin); int N; while(cin>>N){ memset(G,0,sizeof(G)); for(int i=1;i<=N;i++){ int a,b; scanf("%d %d",&a,&b); if(a+b>=N) continue; if(a+b<N && G[a][N-b]+a+b<N) G[a][N-b]++; //G[a][N-b]表示区间(a,N-b]里面元素的个数。 } memset(dp,0,sizeof(dp)); int ans = 0; for(int i=0;i<=N;i++){ dp[i] = max(dp[i],dp[i-1]); for(int j=i+1;j<=N;j++){ if(G[i][j]){ dp[j] = max(dp[j],dp[i]+G[i][j]); } } } printf("%d\n",dp[N]); } } //一直错误的原因就是把G[i][j]+i+N-j>N 的全部抹掉了。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn = 506; struct Node{ int A,B; int num; bool operator < (const Node& rhs) const{ return B > rhs.B; } }group[maxn]; int G[maxn][maxn]; int dp[maxn]; //dp[i]表示前i个人,最大有多少个人没撒谎。 int main() { //freopen("E:\\acm\\input.txt","r",stdin); int N; while(cin>>N){ memset(G,0,sizeof(G)); for(int i=1;i<=N;i++){ int a,b; scanf("%d %d",&a,&b); if(a+b<N && G[a][b]+a+b<N) //这句才是关键。WA的原因。 G[a][b]++; } int cnt = 0; for(int i=0;i<N;i++) for(int j=0;j<N;j++){ if(G[i][j]){ group[cnt].A = i; group[cnt].B = j; group[cnt++].num = G[i][j]; } } sort(group,group+cnt); memset(dp,0,sizeof(dp)); int pv = 0; int i; for(i=1;i<=N;i++){ if(pv >= cnt) break; int a = group[pv].A; int num = group[pv].num; int b = group[pv].B; if(N-b == i){ dp[i] = max(dp[i-1],dp[a]+num); pv++; while(pv < cnt && N-group[pv].B == i){ dp[i] = max(dp[i],dp[group[pv].A]+group[pv].num); pv++; } } else{ dp[i] = dp[i-1]; } } printf("%d\n",dp[i-1]); } }