2019牛客國慶day3-G &CF1238E

牛客G:c++

給定大小爲N的數組a[],給定M組關係,讓你重排a[],使得sum{M隊關係的絕對值之差}最小。首先將a排序,而後依次把a填入數組。數組

假設i在二進制下有x個1,用dp[i]更新dp[i|(1<<j)],表示的是,將a[x+1]填在第j個位置。注意到a[]已經排序了,那麼a[x]的貢獻就是:+以前填的個數*a[x]-沒填的個數*a[x];ui

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=20;
int a[N],p[N],e[N];
ll f[1<<N];
int main(){
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF) {
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        sort(a,a+n); //重排,而後依次填入
        for(int i=0;i<n;i++) {
            e[i]=0;
            p[i]=0;
        }
        for(int i=0;i<m;i++) {
            int a,b;
            scanf("%d%d",&a,&b);
            a--;b--;
            p[a]|=1<<b;p[b]|=1<<a;
            e[a]++,e[b]++;
        }
        f[0]=0;
        for(int i=1;i<(1<<n);i++) {
            f[i]=1e12;
            int k=__builtin_popcount(i)-1; //表示這一輪填a[k]
            for(int j=0;j<n;j++) {
                if(i&(1<<j)) {//表示a[k]填在posj處
                    f[i]=min(f[i],f[i^(1<<j)]+1LL*a[k]*(__builtin_popcount(p[j]&i)*2-e[j]));
                }
            }
        }
        printf("%lld\n",f[(1<<n)-1]);
    }
    return 0;
}

 

CF-E:spa

題意:給定M隊關係(ai,bi),讓你重排,使得{關係的位置絕對值之和}最小。code

依然是枚舉最後一個填誰,那麼這一輪的貢獻是知足(ai已經填入,bi未填入)的個數。blog

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=2000010;
char c[maxn]; int dp[maxn],f[30][30];
int main()
{
    int N,M;
    scanf("%d%d%s",&N,&M,c+1);
    memset(dp,0x3f,sizeof(dp));
    rep(i,1,N-1) f[c[i]-'a'][c[i+1]-'a']++,f[c[i+1]-'a'][c[i]-'a']++;
    dp[0]=0;
    rep(i,0,(1<<M)-1){
        int t=0;
        rep(j,0,M-1) {
            if(i&(1<<j)){
                rep(k,0,M-1)
                 if(!(i&(1<<k))) t+=f[j][k];
            }
        }
        rep(j,0,M-1) if(!(i&(1<<j))) dp[i|(1<<j)]=min(dp[i|(1<<j)],dp[i]+t);
    }
    printf("%d\n",dp[(1<<M)-1]);
    return 0;
}
相關文章
相關標籤/搜索