首页 > 其他 > 详细

【洛谷习题】多米诺骨牌

时间:2018-09-08 15:56:36      阅读:181      评论:0      收藏:0      [点我收藏+]

题目链接:https://www.luogu.org/problemnew/show/P1282


 

花了好长时间终于写出了这道题,主要是状态转移方程比较奇葩,类似于背包问题,难以想到。

呃呃,写得DP不多,对于如何想出状态转移方程还没什么心得,主要是往之前见过的模型上靠。这道题的话,其实可以稍微转化一下设问,变成有n个数,每次操作可以将其变为相反数,问最少操作几次可以使总和的绝对值最小。设dp[i][j]为考虑到第i个数,总和为j时最少的操作次数。状态转移方程为dp[i][j]=min(dp[i-1][j-num[i]],dp[i-1][j+num[i]]+1)。因为是取最小值,一开始要把dp数组初始化成inf,还要将dp[0][0]初始化成0。反正代码细节也还是有的。

技术分享图片
 1 #include<cstdio>
 2 #include<cstring>
 3 const int maxn=1e3+5,maxm=1e4+5,inf=0x3f3f3f3f;
 4 int n,num[maxn],dp[maxn][maxm],mm[maxn],ans;
 5 inline int abs(int x) {return x>0?x:-x;}
 6 inline int map(int x) {return x+5e3+1;}
 7 inline int min(int a,int b) {return a<b?a:b;}
 8 int main() {
 9     scanf("%d",&n);
10     int a,b,sum=0;
11     for(int i=1;i<=n;++i) {scanf("%d%d",&a,&b);num[i]=a-b;}
12     memset(dp,inf,sizeof(dp));
13     for(int i=0;i<=n;++i) {dp[i][map(sum)]=0;sum+=num[i];mm[i]=mm[i-1]+abs(num[i]);}
14     for(int i=1;i<=n;++i)
15         for(int j=-mm[i];j<=mm[i];++j)
16             dp[i][map(j)]=min(dp[i-1][map(j-num[i])],dp[i-1][map(j+num[i])]+1);
17     for(int i=0;i<=mm[n];++i)
18         if(dp[n][map(i)]!=inf||dp[n][map(-i)]!=inf) {
19             ans=min(dp[n][map(i)],dp[n][map(-i)]);
20             break;
21         }
22     printf("%d",ans);
23     return 0;
24 }
AC代码

 

【洛谷习题】多米诺骨牌

原文:https://www.cnblogs.com/Mr94Kevin/p/9609389.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!