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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

【动态规划】 多米诺骨牌 (ssl 1632/luogu 1282)

發布時間:2023/12/3 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【动态规划】 多米诺骨牌 (ssl 1632/luogu 1282) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

多米諾骨牌多米諾骨牌

Description

Input

輸入文件的第一行是一個正整數n(1≤n≤1000),表示多米諾骨牌數。接下來的n行表示n個多米諾骨牌的點數。每行有兩個用空格隔開的正整數,表示多米諾骨牌上下方塊中的點數a和b,且1≤a,b≤6。

Output

輸出文件僅一行,包含一個整數。表示求得的最小旋轉次數。

Sample Input

4

6 1

1 5

1 3

1 2

Sample Output

題目大意:

有n個骨牌,每個骨牌上面和下面都有一個1~6的數,每個骨牌可以上下翻轉,使上下數字反轉,最少翻幾次可以使上面數的總和與下面數的總和的差最少

解題思路:

用一個二維數組f[i][j]來表示前i個骨牌上數減下數(上數:上面的數加在一起,下數:下面的數加在一起)為j時翻轉的最少次數,每一個骨牌不翻時為-上面的數+下面的數(因為遞推要倒著推),翻時為+上面的數-下面的數,然后遞推出結果

動態轉移方程:

f[i][j]=min{f[i?1][j?a[i]+b[i]]f[i?1][j+a[i]?b[i]]+1f[i][j]=min\left\{\begin{matrix}f[i-1][j-a[i]+b[i]]\\ f[i-1][j+a[i]-b[i]]+1\end{matrix}\right.f[i][j]=min{f[i?1][j?a[i]+b[i]]f[i?1][j+a[i]?b[i]]+1?

第一次AC的代碼:

#include<cstdio> #include<iostream> #include<cstring> #define M 6000//設置上限 using namespace std; int n,k,a[1002],b[1001],f[1001][12010]; int main() {memset(f,127/3,sizeof(f));//用min時要先賦一個較大的值scanf("%d",&n);f[0][M]=0;//初值,從0開始,因為有負數,所以從M開始,上限是12000(6000),下限是0(-6000)for (int i=1;i<=n;i++)scanf("%d%d",&a[i],&b[i]);for (int i=1;i<=n;i++)for (int j=1;j<=M*2;j++)//正負數都要f[i][j]=min(f[i-1][j-a[i]+b[i]],f[i-1][j+a[i]-b[i]]+1);//前面的是不翻,后面的是翻k=0;//從0開始while ((f[n][M+k]==f[0][1])&&(f[n][M-k]==f[0][1])) k++;//f[0][1]為一開始的值,有變化時說明可以翻成差值為kprintf("%d",min(f[n][M+k],f[n][M-k]));//輸出最小的 }

優化后的代碼:

#include<cstdio> #include<iostream> #include<cstring> using namespace std; int n,M,k,a[1002],b[1001],f[1001][12005]; int main() {memset(f,127/3,sizeof(f));scanf("%d",&n);M=n*6;//變化主要有M,因為大于n*6的都沒有用,所以這樣可以省時間f[0][M]=0;for (int i=1;i<=n;i++){scanf("%d%d",&a[i],&b[i]);//塞在一起for (int j=M-i*6;j<=M+i*6;j++)//第一次的范圍是-6~6,第二次是-12~12,從M開始,當i加一時,上下的限制各加一,可以省很多時間f[i][j]=min(f[i-1][j-a[i]+b[i]],f[i-1][j+a[i]-b[i]]+1);//動態轉移方程}k=0;//從0開始while ((f[n][M+k]==f[0][1])&&(f[n][M-k]==f[0][1])) k++;//f[0][1]為一開始的值,有變化時說明可以翻成差值為kprintf("%d",min(f[n][M+k],f[n][M-k]));//輸出最小的 }

總結

以上是生活随笔為你收集整理的【动态规划】 多米诺骨牌 (ssl 1632/luogu 1282)的全部內容,希望文章能夠幫你解決所遇到的問題。

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