1. 程式人生 > >洛谷P1282 多米諾骨牌

洛谷P1282 多米諾骨牌

例如 toolbar data blog 兩個 span pan art 一行

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
/*
    背包DP,f[i][j]表示用前i個骨牌每個骨牌其中一個數能夠構成j,如果能夠構成j,
    那麽f[i][j]存儲的就是最小步數,否則存儲inf。
    最後就是和上文最後一步類似,找一個最小的Delta下最小的步數就可以了。
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include
<cmath> #include<cstdlib> #define INF 1000000000 #define maxn 1010 using namespace std; int n,sum,a,b,f[maxn][maxn*10],w=7000,step=INF,D=INF,d; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&a,&b);sum+=a+b; for(int j=0;j<=w;j++)f[i][j]=INF;
if(i==1){f[i][a]=0,f[i][b]=1;continue;} for(int j=1;j<=w;j++){ if(j-a>=0)f[i][j]=min(f[i][j],f[i-1][j-a]); if(j-b>=0)f[i][j]=min(f[i][j],f[i-1][j-b]+1); } } for(int j=1;j<=w;j++){ if(f[n][j]!=INF){ d=abs(sum-j-j); if(d==D)step=min(step,f[n][j]); if(d<D)D=d,step=f[n][j]; } } printf("%d",step); return 0; }

洛谷P1282 多米諾骨牌