日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

P1282 多米诺骨牌 (差值DP+背包)

發布時間:2025/3/20 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P1282 多米诺骨牌 (差值DP+背包) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目描述

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

Solution

此題是一道雙向背包.

這道題一看,就覺得應該和背包有點關系.然后要想到背包的本質是什么.

背包的本質就是通過當前狀態的前驅, 進行更新.

然后就是狀態定義:

f[ i ][ j ] 表示 前 i 個組合里面 上面那個數組的和.?

同時因為無論怎么變化 兩個數列的總和始終是不變的.

所以之后的狀態轉移方程和 背包非常相似.

可以試著自己想一想.

?

Ps: 注意 f[1][ ] 的初始化.

?

代碼(內有一部分注釋) :

#include<bits/stdc++.h> using namespace std; const int maxn=1008; const int inf=1231654;int n,a[maxn],b[maxn];int w[maxn],sum;int f[maxn][6*maxn];//狀態表示 前 i 個里面上一列的值是多少.//同時因為交換不會改變兩列數的總和,所以可以很方便地求出另外一列的值 int main() {scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d%d",&a[i],&b[i]);sum+=(a[i]+b[i]);}//表示 初始狀態. 若第一個換就是 0 否則為1;for(int i=1;i<=n;i++)for(int j=0;j<=n*6+10;j++) f[i][j]=inf;f[1][a[1]]=0; f[1][b[1]]=1;for(int i=2;i<=n;i++)// 注意從 2 開始for(int j=0;j<=n*6;j++){if(j-a[i]>=0)f[i][j]=min(f[i][j], f[i-1][j-a[i]]);//若仍然為a 則不需要去加;if(j-b[i]>=0)f[i][j]=min(f[i][j], f[i-1][j-b[i]]+1);}int minc=inf,mint=inf;for(int i=1;i<=sum;i++){if(f[n][i]!=inf)if(abs(i-(sum-i))<minc)minc=abs(i-(sum-i)),mint=f[n][i];elseif(abs(i-(sum-i))==minc) mint=min(f[n][i],mint);}cout<<mint<<endl;return 0; }

?

?

轉載于:https://www.cnblogs.com/Kv-Stalin/p/8708825.html

總結

以上是生活随笔為你收集整理的P1282 多米诺骨牌 (差值DP+背包)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。