poj 1717 Dominoes

来源:互联网 发布:zbwj后缀是什么软件 编辑:程序博客网 时间:2024/05/21 22:30
/*  Name: poj 1717 Dominoes  Author:UnimenSun  Date: 3/07/11 21:54  Description: 变形0-1背包*//*解题报告:该题为变形的0-1背包,如果能做到很好的转化解决起来不是很难这里将gap值做为背包容量(注意这里gap有可能为负值, 可以给其加上一个定值,将负值变为正值),用反转一次骨牌对gap的影响值change[i]做为物品往背包里放,同样这个影响值,既价值同样有存在负值的情况,与是按0-1背包的思想可得到转移方程:dp[i][j] = min(dp[i-1][j], dp[i-1][j-change[i]]+1):其中i为骨牌号,j为gap值这里需要注意动规数组存放的值是意思,这一点必须弄清,其实该数组中存放的值为:要使差值改变gap最少的反转次数(这里要好好理解)正是由于动规数组里存放着这样的值,因此在最后只要找到一个这样的值就行:与fix+gap最接近的i,同时dp[fix+gap-i]或dp[fix+gap+i]有值即可,注意如果对称着都存在值,取出两者中最小的即可*/#include <iostream>#include <algorithm>using namespace std;const int nmax = 19870711;const int fix = 20000;int n;int dp[35000];int up, down, gap;int change[1010];int nright, nletf;int main(){int i, j;while(cin>>n){//初始化gap = 0;nright = nletf = fix;for(i=fix-n*12; i<=fix+n*12; ++i)dp[i] = nmax;dp[fix] = 0; //读入数据for(i=1; i<=n; ++i){cin>>up>>down;change[i] = (up - down) * 2;gap += (up - down);}//0-1背包处理for(i=1; i<=n; ++i){if(change[i] > 0)for(j=nright+change[i]; j>=nletf+change[i]; --j)dp[j] = _cpp_min(dp[j], dp[j-change[i]]+1);if(change[i] < 0)for(j=nletf+change[i]; j<=nright+change[i]; ++j)dp[j] = _cpp_min(dp[j], dp[j-change[i]]+1);nright = _cpp_max(nright, nright+change[i]);nletf = _cpp_min(nletf, nletf+change[i]);}//找最优解int ans;for(i=0; i<=n*12; ++i){if(dp[fix+gap-i]<nmax || dp[fix+gap+i]<nmax){ans = _cpp_min(dp[fix+gap-i], dp[fix+gap+i]);break;}} cout<<ans<<endl;}return 0;}

原创粉丝点击