程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> HDU 4293 Groups(12年成都網絡賽-DP)

HDU 4293 Groups(12年成都網絡賽-DP)

編輯:C++入門知識

題目鏈接:Click here~~
題意:
有 n 個人,可任意分成若干組,然後每個人各提供一個信息,表示他們組前面有多少個人,後面有多少個人。問最多有多少個信息是不沖突的。
解題思路:
可以把 n 個人看成一段區間 [1,n]。
設每個人的信息是a、b,則這個信息代表了他們組所在的區間 S 為 [a+1,n-b]。
若某些人是一組的,當且僅當他們信息所代表的區間是相同的。
當你相信其中某一個人說的話的時候,你必定會相信另一個人所說的相同的話,於是我們可以將這些相同的區間合並到一起,記錄一下值。
問題轉化成了在 [1,n] 這段區間中分布的若干個帶有權值的區間,問如何選取一些不相交的區間,使權值之和最大。

我的做法是先按照區間的右端點進行排序,然後設 dp[ i ] 表示選取第 i 個區間時,區間 [1,S[ i ].b] 能取到的最大權值和。
則 dp[ i ] = num[ i ] + max{ dp[ j ] } (j < i 且 S[ j ].b < S[ i ].a)。

最後找到最大的 dp[ i ] 即為解。
[cpp]
#include <stdio.h> 
#include <string.h> 
#include <algorithm> 
using namespace std; 
 
#define N 505 
 
struct Int 

    int a,b; 
    Int(){} 
    Int(int _a,int _b):a(_a),b(_b){} 
    bool operator < (const Int& s)const 
    { 
        return b < s.b || b == s.b && a < s.a; 
    } 
}S[N]; 
 
int num[N][N],dp[N]; 
 
int main() 

    int n,a,b; 
    while(~scanf("%d",&n)) 
    { 
        int m = 0; 
        memset(num,0,sizeof(num)); 
        memset(dp,0,sizeof(dp)); 
        for(int i=0;i<n;i++) 
        { 
            scanf("%d%d",&a,&b); 
            if(a+b > n-1 || num[a+1][n-b] == n-b-a) 
                continue; 
            if(!num[a+1][n-b]) 
                S[m++] = Int(a+1,n-b); 
            ++num[a+1][n-b]; 
        } 
        sort(S,S+m); 
        int ans = 0; 
        for(int i=0;i<m;i++) 
        { 
            int mmax = 0; 
            for(int j=0;j<i;j++) 
                if(S[j].b < S[i].a) 
                    mmax = max(mmax,dp[j]); 
            dp[i] = mmax + num[S[i].a][S[i].b]; 
            ans = max(ans,dp[i]); 
        } 
        printf("%d\n",ans); 
    } 
    return 0; 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved