• 洛谷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
    

    啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊好鸡冻啊啊啊啊啊

    好久没自己A过DP题了

    $dp[i][j]$表示枚举到第$i$个数,差为$j$所需要的最少步数

    然后枚举一下,看一下这个状态是否能够达到

    有点类似背包问题

    注意在这个题目中数组有可能越界

    所以我用1000来当做0

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int MAXN=2001;
     6 inline char nc()
     7 {
     8     static char buf[MAXN],*p1=buf,*p2=buf;
     9     return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++;
    10 }
    11 inline int read()
    12 {
    13     char c=nc();int x=0,f=1;
    14     while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();}
    15     while(c>='0'&&c<='9'){x=x*10+c-'0';c=nc();}
    16     return x*f;
    17 }
    18 inline int work(int x)
    19 {
    20     int ans=0;
    21     for(int i=1;i<x;i++)   
    22         if(x%i==0)  ans+=i;
    23     return ans;
    24 }
    25 int dp[MAXN][2*MAXN];
    26 int a[MAXN],b[MAXN];
    27 int zero=1000;
    28 int main()
    29 {
    30     #ifdef WIN32
    31     freopen("a.in","r",stdin);
    32     #else
    33     #endif
    34     int n=read();
    35     for(int i=1;i<=n;i++)    a[i]=read(),b[i]=read();
    36     memset(dp,0x3f,sizeof(dp));
    37     dp[0][1000]=0;
    38     for(int i=1;i<=n;i++)
    39     {
    40         for(int j=0;j<=2001;j++)
    41         {
    42             if(dp[i-1][j]<100000)
    43             {
    44                 dp[i][j+(a[i]-b[i])]=min(dp[i][j+(a[i]-b[i])],dp[i-1][j]);
    45                 dp[i][j+(b[i]-a[i])]=min(dp[i][j+(b[i]-a[i])],dp[i-1][j]+1);
    46             }
    47         }
    48     }
    49     int anspos=0x7ffff,ans=0x7ffff;
    50     for(int i=1;i<=2001;i++)
    51         if(dp[n][i]<=10000&&abs(i-1000)<=anspos)
    52             anspos=abs(i-1000);
    53     for(int i=1;i<=2001;i++)
    54         if(abs(i-1000)==anspos)
    55             ans=min(ans,dp[n][i]);
    56     printf("%d",ans);
    57         
    58     return 0;
    59 } 
    60                     
  • 相关阅读:
    使用Xshell和Xftp部署简单的项目
    1-27 sed基本编程和cut基本应用
    1-26-1-expect无交互式-正则表达式
    1-24-case流程控制和while循环语句的使用
    1-23-shell脚本之-if流程控制语句和for循环语句的使用
    1-22-shell脚本基本应用-实验手册
    1-22-shell脚本的基础
    1-21 网络管理相关的命令
    总结 1-1 ~ 1-6
    windows系统下Eclipse启动界面更改
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/7912045.html
Copyright © 2020-2023  润新知