/*
poj 1717 填满型背包
解题思路:
1、枚举所有差值,计算每个差值需要的最少旋转次数
f(i, j)表示前i张骨牌,上下值差为j时的最少旋转次数
f(i, j) = min (f(i-1, j-di), f(i-1, j+di)+1)
前i-1张骨牌差值为j-di翻转次数 和 差值为j+di翻转次数加1 取最小值即是!
另外:
f(i, j) != i - f(i, -j)
1 2 1
2 1 2
f(3, -1) = 0
f(3, 1) = 1
其实f(i, j)最大等于i - f(i, -j),可以通过反证法证明
*/
#include <iostream>
#include <algorithm>
namespace {
using namespace std;
const int N_MAX = 1000;
int diff[N_MAX+1];
const int INFINITY = 65535;
const int GAP_MAX = 6000;
int f[N_MAX+1][2*GAP_MAX+1];
int n, diff_max;
void reset()
{
for (int i=0; i<=n; i++)
{
for (int j=-diff_max; j<=diff_max; j++)
{
f[i][j+GAP_MAX] = INFINITY;
}
}
f[0][GAP_MAX] = 0;
}
int domino_1717()
{
reset();
for (int i=1; i<=n; i++)
{
for (int j=-diff_max; j<=diff_max; j++)
{
int k = j-diff[i], l = j+diff[i];
if (-diff_max<=k && k<=diff_max && f[i-1][k+GAP_MAX]!=INFINITY)
{
f[i][j+GAP_MAX] = min(f[i][j+GAP_MAX], f[i-1][k+GAP_MAX]);
}
if (-diff_max<=l && l<=diff_max && f[i-1][l+GAP_MAX]!=INFINITY)
{
f[i][j+GAP_MAX] = min(f[i][j+GAP_MAX], f[i-1][l+GAP_MAX]+1);
}
}
}
int min_turn = INFINITY;
for (int k=0; k<diff_max; k++)
{
if (f[n][GAP_MAX+k] != INFINITY)
{
min_turn = min(min_turn, f[n][GAP_MAX+k]);
}
if (f[n][GAP_MAX-k] != INFINITY)
{
min_turn = min(min_turn, f[n][GAP_MAX-k]);
}
if (min_turn != INFINITY)
{
break;
}
}
return min_turn;
}
}
int main()
{
int a, b;
cin >> n;
for (int i=1; i<=n; i++)
{
cin >> a >> b;
diff[i] = a - b;
}
diff_max = 6 * n;
cout << domino_1717() << endl;
return 0;
}
poj 1717 多米诺问题
最新推荐文章于 2020-06-03 21:11:32 发布