首页 > 代码库 > 洛谷P1282 多米诺骨牌
洛谷P1282 多米诺骨牌
洛谷P1282 多米诺骨牌
动态规划
题意: 对多米诺骨牌进行翻转,使其上下值最接近,求最小的翻转次数
1、状态 dp[ i ][ j ] 表示上面那排前i个数 和为 j 所需要的最小的翻转次数
2、状态转移方程
dp[ i ][ j ] = min(dp[ i ][ j ],dp[ i-1 ][ j-a[ i ] ] ) ;
dp[ i ][ j ] = min(dp[ i ][ j ],dp[ i-1 ][ j-b[ i ] ]+1 ) ;
3、初始值
dp[ i ][ j ] = inf dp[ 0 ][ 0 ] = 0
4、枚举顺序
显然 i 最先枚举 然后 是 j
5、边界 i 枚举 1--n j 枚举 0--max 要求 j - a[ i ] >0 j -b[ i ] > 0
6、答案 从tot (所有a[i]b[i] 总和) /2 向 0 枚举 第一个不为 inf 的 点
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iomanip> 8 #include <iostream> 9 using namespace std ; 10 11 const int maxn = 1001,inf = 1e9 ; 12 int n,tot,v,x,ans ; 13 int a[maxn],b[maxn],dp[maxn][6001] ; 14 15 int main() 16 { 17 scanf("%d",&n) ; 18 for(int i=1;i<=n;i++) 19 { 20 scanf("%d%d",&a[ i ],&b[ i ]) ; 21 tot = tot + a[ i ] + b[ i ] ; 22 v = v + max( a[ i ],b[ i ] ) ; 23 } 24 25 for(int i=0;i<=n;i++) 26 for(int j=0;j<=v;j++) dp[i][j] = inf ; 27 dp[ 0 ][ 0 ] = 0 ; 28 for(int i=1;i<=n;i++) 29 { 30 for(int j=0;j<=v;j++) 31 { 32 if(j-a[ i ]>=0) dp[ i ][ j ] = min(dp[ i ][ j ],dp[ i-1 ][ j-a[i] ]) ; 33 if(j-b[ i ]>=0) dp[ i ][ j ] = min(dp[ i ][ j ],dp[ i-1 ][ j-b[i] ]+1) ; 34 } 35 } 36 37 x = tot>>1 ; 38 for(int i=x;i;i--) 39 { 40 ans = min(dp[n][i],dp[n][tot-i]) ; 41 if(ans<inf) 42 { 43 printf("%d\n",ans ) ; 44 return 0 ; 45 } 46 } 47 48 return 0 ; 49 }
洛谷P1282 多米诺骨牌
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。