洛谷P1282 多米諾骨牌
阿新 • • 發佈:2017-10-13
例如 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 多米諾骨牌