zoukankan      html  css  js  c++  java
  • poj 1717==洛谷P1282 多米诺骨牌

    Dominoes
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 6571   Accepted: 2178

    Description

    A domino is a flat, thumbsized tile, the face of which is divided into two squares, each left blank or bearing from one to six dots. There is a row of dominoes laid out on a table:

    The number of dots in the top line is 6+1+1+1=9 and the number of dots in the bottom line is 1+5+3+2=11. The gap between the top line and the bottom line is 2. The gap is the absolute value of difference between two sums.

    Each domino can be turned by 180 degrees keeping its face always upwards.

    What is the smallest number of turns needed to minimise the gap between the top line and the bottom line?

    For the figure above it is sufficient to turn the last domino in the row in order to decrease the gap to 0. In this case the answer is 1.
    Write a program that: computes the smallest number of turns needed to minimise the gap between the top line and the bottom line.

    Input

    The first line of the input contains an integer n, 1 <= n <= 1000. This is the number of dominoes laid out on the table.

    Each of the next n lines contains two integers a, b separated by a single space, 0 <= a, b <= 6. The integers a and b written in the line i + 1 of the input file, 1 <= i <= 1000, are the numbers of dots on the i-th domino in the row, respectively, in the top line and in the bottom one.

    Output

    Output the smallest number of turns needed to minimise the gap between the top line and the bottom line.

    Sample Input

    4
    6 1
    1 5
    1 3
    1 2
    

    Sample Output

    1
    

    Source

    P1282 多米诺骨牌

    • 题目提供者该用户不存在
    • 标签动态规划
    • 难度提高+/省选-
    • 通过/提交316/1095

    提交该题 讨论 题解 记录

    题目描述

    多米诺骨牌有上下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

    风格1:
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    int const N=1010;
    int const inf=0x3f3f3f3f;
    int a[N],b[N],n;
    int f[N][N*6*2];//表示差值+p为j时的最小次数
    int main(){
        memset(f,0x3f,sizeof(f));
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d%d",a+i,b+i);
        int v=n*6*2;
        int p=n*6;
        f[0][p]=0;
        //以下部分是两种不同的区间平移  其实第二种看起来更清晰 而且第一种会出现下标越界的情况 但是不知道为何竟然A了
        for(int i=1;i<=n;i++){
            for(int j=0;j<=v;j++){
                f[i][j]=min(f[i-1][j-(a[i]-b[i])],f[i-1][j-(b[i]-a[i])]+1);
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=-p;j<=p;j++){
                f[i][j+p]=min(f[i-1][j+a[i]-b[i]+p],f[i-1][j+b[i]-a[i]+p]+1);
            }
        }
        //
        for(int i=0;i<=p;i++){
            if(min(f[n][p+i],f[n][p-i])!=inf){
                printf("%d
    ",min(f[n][p+i],f[n][p-i]));
                return 0;
            }
        }
    }
    
    
    风格2:
    
    
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define ref(i,x,y)for(register int i=x;i<=y;i++)
    #define def(i,x,y)for(register int i=x;i>=y;i--)
    #define Q 2000 
    int a,b,n,nn,w[1010];
    int f[1010][10100];
    void first(){
        scanf("%d",&n);
        ref(i,1,n) scanf("%d%d",&a,&b),w[i]=a-b;
    }
    void go(){
        nn=5*n;
        memset(f,127,sizeof(f));
        f[1][w[1]+nn]=0;
        f[1][-w[1]+nn]=1;
        ref(i,2,n) def(j,10*n,0){
            if(j+w[i]>=0&&j+w[i]<=10*n) 
              f[i][j]=min(f[i][j],f[i-1][j+w[i]]+1);
            if(j-w[i]>=0&&j-w[i]<=10*n) 
              f[i][j]=min(f[i][j],f[i-1][j-w[i]]);  
        }
        if(f[n][5*n]<Q) {printf("%d
    ",f[n][5*n]);return;}
        else{
            for(int i=nn-1,j=nn+1;i>=1&&j<=2*nn;i--,j++){
                if(f[n][i]<Q||f[n][j]<Q){
                  printf("%d
    ",min(f[n][i],f[n][j]));
                  return;
                }  
            }    
        }
    }
    int main(){
        first();
        go();
        return 0;
    }
    
    
    
     
  • 相关阅读:
    redis连接客户端
    map中使用的细节问题(不同key循坏中被后面的值替换)
    使用异步开启新的线程Spring异步方法注解@Async
    npm init 出现一堆提问(npm init -y)
    小程序的时间日期选择器
    小程序--分类项目跳转页面(同样也适用轮播图跳转)
    小程序样式不管用,解决方法button:not([size='mini']) { width: 184px; margin-left: auto; margin-right: auto; }
    vue-elementui的时间日期选择器( value-format="yyyy-MM-dd HH:mm:ss"),以及时间解析{y}-{m}-{d} {h}:{i}:{s}
    vue.config.js配置详细说明(逐条解释)
    element在el-table-column中如何使用过滤器
  • 原文地址:https://www.cnblogs.com/shenben/p/5616848.html
Copyright © 2011-2022 走看看