C++ P1282 多米诺骨牌

题目描述

多米诺骨牌有上下2个方块组成,每个方块中有1~6个点。现有排成行的

上方块中点数之和记为S1,下方块中点数之和记为S2,它们的差为|S1-S2|。例如在图8-1中,S1=6+1+1+1=9,S2=1+5+3+2=11,|S1-S2|=2。每个多米诺骨牌可以旋转180°,使得上下两个方块互换位置。 编程用最少的旋转次数使多米诺骨牌上下2行点数之差达到最小。

对于图中的例子,只要将最后一个多米诺骨牌旋转180°,可使上下2行点数之差为0。

输入输出格式

输入格式:

输入文件的第一行是一个正整数n(1≤n≤1000),表示多米诺骨牌数。接下来的n行表示n个多米诺骨牌的点数。每行有两个用空格隔开的正整数,表示多米诺骨牌上下方块中的点数a和b,且1≤a,b≤6。

输出格式:

输出文件仅一行,包含一个整数。表示求得的最小旋转次数。

输入输出样例

输入样例#1: 

4
6 1
1 5
1 3
1 2

输出样例#1: 

1

题目地址:https://www.luogu.org/problemnew/show/P1282


#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int up,down,ans,n,a[1100],d[1100];
int main(){
    cin>>n;
    int p,q;
    for(int o=1;o<=n;o++){
        scanf("%d%d",&p,&q);
        a[o]=p-q;
        up+=p,down+=q;
    }
    int s=down-up;
    if(s==0){cout<<0;return 0;}
    sort(a+1,a+1+n);
    if(s<0){
        for(int i=n;i>=1;i--){
            if(a[i]>0 && s+a[i]*2<=0)
                s+=(a[i]*2),ans++;
            else continue;
        }
    }
    if(s>0){
        for(int i=1;i<=n;i++){
            if(a[i]<0 && s+a[i]*2>=0)
                s+=(a[i]*2),ans++;
            else continue;
        }
    }
    int maxn=0;
    int k=1;
    for(int i=1;i<=n;i++){
        maxn=0;
        for(int j=i+1;j<=n;j++){
            int c=a[i]+a[j];
            if(abs(s)>abs(s+(c*2)) && abs(c)>abs(maxn)){
                d[k]=c; 
                maxn=c;
            }
        }
        k++;
    }
    sort(d+1,d+k+1);
    for(int i=k;i>=1;i--){
        if(abs(s)>abs(s+d[i]*2)){
            ans+=2;
            s+=d[i]*2;
        }
    }
    cout<<ans<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/zbsy-wwx/p/11680657.html