ICPCCamp 2016 Day 4 - SJTU Dreadnought Contest(The Road Network-区间dp)

有n个城市,每个城市有一个 wi ,如果两座城市满足 wi+wjd ,则在两座城市连边。
现在把城市分成2个点集,是2点集之间的边的数量尽量多,求最大数量,方案数。
1n2000,0d109

区间dp,将w排序
考虑2个极端情况
1.当w1与wn不连边
此时w1不与任何点连边
2.w1与wn连边
此时wn与所有点连边
然后都懂得

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <functional>
#include <cstdlib>
#include <queue>
#include <stack>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p]) 
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 

const int MAXN =(2000+10);
ll w[MAXN],d;
int n,f[MAXN][MAXN],g[MAXN][MAXN]={0};
int vis[MAXN][MAXN]={0};
int T=0;   
int work(int i,int j,int x,int l) {

    if (vis[l][x]==T) return f[l][x];
    vis[l][x]=1; f[l][x]=g[l][x]=0;
    if (x>l || x<0) {
        return -2000*2000;
    }

    if (l==1  ) {
        g[l][x]=1;
        return 0;
    }

    if (w[i]+w[j]<d) {
        if (x==0) {
            f[l][x] = work(i+1,j,x,l-1);
            g[l][x] = g[l-1][x];
            return f[l][x];
        }
        f[l][x]=work(i+1,j,x-1,l-1);
        g[l][x]=g[l-1][x-1];
        if (l>x) {
            f[l][x] = max( work(i+1,j,x,l-1), f[l][x]);
            if (work(i+1,j,x-1,l-1) < work(i+1,j,x,l-1)) g[l][x]=g[l-1][x];
            if (work(i+1,j,x-1,l-1) == work(i+1,j,x,l-1)) g[l][x]=(g[l-1][x]+g[l-1][x-1])%F;
        }
    }
    else {
        if (x==0) {
            f[l][x] = work(i,j-1,x,l-1)+x;
            g[l][x] = g[l-1][x];
            return f[l][x];
        }
        f[l][x]=work(i,j-1,x-1,l-1) + l-x;
        g[l][x]=g[l-1][x-1];

        if (l>x) {
            f[l][x]=max(f[l][x],work(i,j-1,x,l-1)+x );
            if (work(i,j-1,x-1,l-1) + l-x < work(i,j-1,x,l-1)+x ) g[l][x]=g[l-1][x];
            if (work(i,j-1,x-1,l-1) + l-x == work(i,j-1,x,l-1)+x ) g[l][x]=(g[l-1][x]+g[l-1][x-1])%F;
        } 
    }
    return f[l][x];
}

int main() {

    cin>>n>>d;
    For(i,n) cin>>w[i];
    sort(w+1,w+1+n);

    int ans1=-1,ans2=0;
    ++T;
// cout<<work(2,4,1,3)<<' '<<g[3][1]<<endl;
    Rep(x,n+1) {
         work(1,n,x,n);
         if (ans1<f[n][x] ) ans1=f[n][x] , ans2 = g[n][x];
         else if (ans1 == f[n][x] ) ans2= (ans2+ g[n][x] )%F;

    }

    cout << ans1 << ' '<< ans2 << endl;
    return 0;
}

你可能感兴趣的:(ICPCCamp 2016 Day 4 - SJTU Dreadnought Contest(The Road Network-区间dp))