洛谷P1282 多米诺骨牌
Posted 自为
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷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
啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊好鸡冻啊啊啊啊啊
好久没自己A过DP题了
$dp[i][j]$表示枚举到第$i$个数,差为$j$所需要的最少步数
然后枚举一下,看一下这个状态是否能够达到
有点类似背包问题
注意在这个题目中数组有可能越界
所以我用1000来当做0
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int MAXN=2001; 6 inline char nc() 7 { 8 static char buf[MAXN],*p1=buf,*p2=buf; 9 return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++; 10 } 11 inline int read() 12 { 13 char c=nc();int x=0,f=1; 14 while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=nc();} 15 while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=nc();} 16 return x*f; 17 } 18 inline int work(int x) 19 { 20 int ans=0; 21 for(int i=1;i<x;i++) 22 if(x%i==0) ans+=i; 23 return ans; 24 } 25 int dp[MAXN][2*MAXN]; 26 int a[MAXN],b[MAXN]; 27 int zero=1000; 28 int main() 29 { 30 #ifdef WIN32 31 freopen("a.in","r",stdin); 32 #else 33 #endif 34 int n=read(); 35 for(int i=1;i<=n;i++) a[i]=read(),b[i]=read(); 36 memset(dp,0x3f,sizeof(dp)); 37 dp[0][1000]=0; 38 for(int i=1;i<=n;i++) 39 { 40 for(int j=0;j<=2001;j++) 41 { 42 if(dp[i-1][j]<100000) 43 { 44 dp[i][j+(a[i]-b[i])]=min(dp[i][j+(a[i]-b[i])],dp[i-1][j]); 45 dp[i][j+(b[i]-a[i])]=min(dp[i][j+(b[i]-a[i])],dp[i-1][j]+1); 46 } 47 } 48 } 49 int anspos=0x7ffff,ans=0x7ffff; 50 for(int i=1;i<=2001;i++) 51 if(dp[n][i]<=10000&&abs(i-1000)<=anspos) 52 anspos=abs(i-1000); 53 for(int i=1;i<=2001;i++) 54 if(abs(i-1000)==anspos) 55 ans=min(ans,dp[n][i]); 56 printf("%d",ans); 57 58 return 0; 59 } 60
以上是关于洛谷P1282 多米诺骨牌的主要内容,如果未能解决你的问题,请参考以下文章