BZOJ1237: [SCOI2008]配对

题意:给定两个数组 构造一个配对 使得每个位置上之差的和最小 大小相同的不能配对

题解:猜了一下 应该把两个数组排序一下 答案最小

   处理相同的不能配对的时候 那么应该找就近的交换

   猜一下 如果有合法方案的话 肯定一个大小为3的环就能解决配对问题了

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF = 1e12;
 
int q[100005];
int w[100005];
ll dp[100005];
 
ll abss(ll x, ll y)
{
    if(x == y) return INF;
    else if(x > y) return x - y;
    else if(x < y) return y - x;
}
 
int main()
{
    dp[0] = 0;
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%d%d", &q[i], &w[i]), dp[i] = INF;
    sort(q + 1, q + 1 + n);
    sort(w + 1, w + 1 + n);
 
    for(int i = 1; i <= n; i++)
    {
        if(i >= 1 && dp[i - 1] != INF)
        {
            //if(i == 3) cout<<"hi"<<endl;
            ll x = abss(q[i], w[i]);
            dp[i] = min(dp[i], dp[i - 1] + x);
            //if(i == 3) cout<<dp[i]<<endl;
        }
        if(i >= 2 && dp[i - 2] != INF)
        {
            ll x1 = abss(q[i], w[i - 1]);
            ll x2 = abss(q[i - 1], w[i]);
            dp[i] = min(dp[i], dp[i - 2] + x1 + x2);
            //if(i == 3) cout<<dp[i]<<endl;
        }
        if(i >= 3 && dp[i - 3] != INF)
        {
            ll x1 = abss(q[i], w[i - 2]);
            ll y1 = abss(q[i - 1], w[i - 1]);
            ll y2 = abss(q[i - 2], w[i]);
            dp[i] = min(dp[i], dp[i - 3] + y1 + y2 + x1);
 
            ll z1 = abss(q[i - 1], w[i]);
            ll z2 = abss(q[i - 2], w[i - 1]);
            dp[i] = min(dp[i], dp[i - 3] + z1 + z2 + x1);
 
            ll o1 = abss(q[i], w[i - 1]);
            ll o2 = abss(q[i - 1], w[i - 2]);
            ll o3 = abss(q[i - 2], w[i]);
            dp[i] = min(dp[i], dp[i - 3] + o1 + o2 + o3);
            //if(i == 3) cout<<dp[i]<<endl;
        }
    }
    //for(int i = 1; i <= n; i++) cout<<dp[i]<<endl;
 
    if(dp[n] == INF) puts("-1");
    else printf("%lld\n", dp[n]);
    return 0;
}
View Code

 

posted @ 2018-10-03 20:58  lwqq3  阅读(141)  评论(0编辑  收藏  举报