目前共有10篇帖子。 内容转换:不转换▼
 
点击 回复
479 9
【试题】剪格子
一派护法 十九级
1楼 发表于:2016-3-19 17:22
// 参考资料: http://blog.csdn.net/xushao_movens/article/details/50637251
#include <iostream>

using namespace std;

#define MAXN 15
#define NO_ANSWER 0xffff

int m, n;
int grid[MAXN][MAXN];
int dir[4][2] = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}};
int used[MAXN][MAXN];
int ans;

// 求另一区域的和
// 参数cnt用于返回另一区域的格子数
int rest_sum(int *cnt)
{
    int sum = 0;
    int i, j;
    *cnt = 0;
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < m; j++)
        {
            if (!used[i][j])
            {
                (*cnt)++;
                sum += grid[i][j];
            }
        }
    }
    return sum;
}

//搜索到(x, y)时左上角区域和sum
void dfs(int x, int y, int sum)
{
    used[x][y] = true;

    int cnt, temp;
    int restSum = rest_sum(&cnt);
    if (sum == restSum)
    {
        temp = n * m - cnt; // 总格子数减去另一区域的格子数, 得到本区域格子数
        if (ans > temp)
            ans = temp; // 求最小答案
        return;
    }

    int i;
    for (i = 0; i < 4; i++) // 四个方向
    {
        // 新坐标
        int nx = x + dir[i][0];
        int ny = y + dir[i][1];

        // 坐标有效且未被使用
        if (nx >= 0 && nx < n && ny >= 0 && ny < m && !used[nx][ny])
        {
            used[nx][ny] = true; // 标记使用
            dfs(nx, ny, sum + grid[nx][ny]); // 寻找子空间的更多解
            used[nx][ny] = false; // 回溯, 恢复原来状态
        }
    }
}

int main(void)
{
    // 输入数据
    int i, j;
    cin >> m >> n;
    memset(used, 0, sizeof(used));
    ans = NO_ANSWER;
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < m; j++)
            cin >> grid[i][j];
    }

    // 搜索
    dfs(0, 0, grid[0][0]);

    // 输出结果
    if (ans == NO_ANSWER) // 无答案
        cout << 0 << endl;
    else
        cout << ans << endl;
    return 0;
}
一派护法 十九级
2楼 发表于:2016-3-19 17:54
正确  100  15ms  2.5MB  
一派护法 十九级
3楼 发表于:2016-3-20 21:19
今天就考了一个与此题非常类似的题:剪邮票
一派护法 十九级
4楼 发表于:2016-5-23 13:40
回复3楼 @巨大八爪鱼 的内容:
今天就考了一个与此题非常类似的题:剪邮票
https://zh.arslanbar.net/post.php?t=24044
一派护法 十九级
5楼 发表于:2016-5-23 14:51
【代码2:使用变量x、y】
#include <iostream>

using namespace std;

#define MAXN 15
#define NO_ANSWER 0xffff

int m, n;
int grid[MAXN][MAXN];
int dir[][2] = {-1, 0, 1, 0, 0, 1, 0, -1};
bool used[MAXN][MAXN];
int ans = NO_ANSWER;

// 求另一区域(used=0)的和
// 参数cnt用于返回另一区域的格子数
int rest_sum(int *cnt)
{
    int sum = 0;
    int x, y;
    *cnt = 0;
    for (y = 0; y < n; y++)
    {
        for (x = 0; x < m; x++)
        {
            if (!used[y][x])
            {
                (*cnt)++;
                sum += grid[y][x];
            }
        }
    }
    return sum;
}

// 搜索到(x, y)时左上角区域的和sum
void search(int x, int y, int sum)
{
    used[y][x]  = true;

    int grid_num[2];
    int sum2 = rest_sum(&grid_num[1]);
    if (sum == sum2)
    {
        grid_num[0] = m * n - grid_num[1]; // 总格子数减去另一区域的格子数, 得到本区域格子数
        if (ans > grid_num[0]) // ans一开始是一个非常大的数
            ans = grid_num[0]; // 求最小答案
        return;
    }

    int i;
    for (i = 0; i < 4; i++) // 4个方向
    {
        // 新坐标
        int x_new = x + dir[i][0];
        int y_new = y + dir[i][1];

        // 坐标有效且未被使用
        if (x_new >= 0 && x_new < m && y_new >= 0 && y_new < n && !used[y_new][x_new])
        {
            used[y_new][x_new] = true; // 标记使用
            search(x_new, y_new, sum + grid[y_new][x_new]);
            used[y_new][x_new] = false; // 回溯, 恢复原来状态
        }
    }
}

int main(void)
{
    int x, y;
    memset(used, 0, sizeof(used));
    cin >> m >> n;
    for (y = 0; y < n; y++)
    {
        for (x = 0; x < m; x++)
            cin >> grid[y][x];
    }

    search(0, 0, grid[0][0]);

    if (ans == NO_ANSWER)
        cout << 0 << endl;
    else
        cout << ans << endl;

    return 0;
}
一派护法 十九级
6楼 发表于:2016-5-23 15:48
【PHP代码:生成直观网页】
<?php
define('NO_ANSWER', 0xffff); // 这个常量不要改动
define('TABLE_FLOAT', true); // 决定显示方式

function draw_table($sum1, $sum2, $margin = 0, $correct = false) {
    global $m, $n, $grid, $used;
    if ($correct) {
        $cls = 'correct';
    } else {
        $cls = 'used';
    }
    if (TABLE_FLOAT) {
        $style = ' style="float:left"';
    } else {
        $style = " style=\"margin-left:{$margin}px\"";
    }
    echo "<table border=\"1\" $style>\n";
    for ($y = 0; $y < $n; $y++) {
        echo "\t<tr>\n";
        for ($x = 0; $x < $m; $x++) {
            if ($used[$y][$x]) {
                printf("\t\t<td class=\"%s\">%d</td>\n", $cls, $grid[$y][$x]);
            } else {
                printf("\t\t<td>%d</td>\n", $grid[$y][$x]);
            }
        }
        echo "\t</tr>\n";
    }
    echo "\t<tr>\n\t\t<td class=\"$cls\" colspan=\"$m\">sum1=$sum1</td>\n\t</tr>\n";
    echo "\t<tr>\n\t\t<td colspan=\"$m\">sum2=$sum2</td>\n\t</tr>\n";
    echo "</table>\n";
}

function calc_rest_sum(&$cnt) {
    global $m, $n, $used, $grid;
    $sum = 0;
    $cnt = 0;
    for ($y = 0; $y < $n; $y++) {
        for ($x = 0; $x < $m; $x++) {
            if (!$used[$y][$x]) {
                $cnt++;
                $sum += $grid[$y][$x];
            }
        }
    }
    return $sum;
}

function search($x, $y, $sum, $margin = 0) {
    global $m, $n, $used, $grid, $ans;
    $dir = array(array(-1, 0), array(1, 0), array(0, 1), array(0, -1));
    $used[$y][$x] = true;
    $grid_num = array();
    $sum2 = calc_rest_sum($grid_num[1]);
    if ($sum == $sum2) {
        $grid_num[0] = $m * $n - $grid_num[1];
        if ($ans > $grid_num[0]) {
            $ans = $grid_num[0];
        }
        draw_table($sum, $sum2, $margin, true);
        return;
    } else {
        draw_table($sum, $sum2, $margin);
    }
   
    for ($i = 0; $i < 4; $i++) {
        $x_new = $x + $dir[$i][0];
        $y_new = $y + $dir[$i][1];
        if ($x_new >= 0 && $x_new < $m && $y_new >= 0 && $y_new < $n && !$used[$y_new][$x_new]) {
            $used[$y_new][$x_new] = true;
            search($x_new, $y_new, $sum + $grid[$y_new][$x_new], $margin + 40);
            $used[$y_new][$x_new] = false;
        }
    }
}

/*$grid = array();
$grid[0] = array(1, 1, 1, 1);
$grid[1] = array(1, 30, 80, 2);
$grid[2] = array(1, 1, 1, 100);*/

$grid = array(array(10, 1, 52), array(20, 30, 1), array(1, 2, 3));

$m = count($grid[0]);
$n = count($grid);
$ans = NO_ANSWER;

$used = array();
for ($y = 0; $y < $n; $y++) {
    $used[$y] = array_fill(0, $m, false);
}
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>剪格子</title>
<style>
body {
    font-family: Arial;
    font-size: 14px;
}
table {
    border-collapse: collapse;
    font-weight: bold;
    margin-bottom: 10px;
    margin-right: 10px;
}
td {
    background-color: pink;
    text-align: center;
    width: 30px;
    height: 30px;
}
td.used {
    background-color: yellow;
}
td.correct {
    background-color: red;
}
</style>
</head>

<body>
<?php
search(0, 0, $grid[0][0]);
?>
<div style="clear:both"><b>最终结果: </b><?=$ans?></div>
</body>
</html>
一派护法 十九级
7楼 发表于:2016-5-23 15:50
一派护法 十九级
8楼 发表于:2016-5-23 19:51
【纯PHP版代码】
<?php
define('NO_ANSWER', 0xffff);
$GLOBALS['answer'] = NO_ANSWER;

$GLOBALS['grid'] = array(array(1, 1, 1, 1), array(1, 30, 80, 2), array(1, 1, 1, 100)); // 数据

$GLOBALS['m'] = count($grid[0]);
$GLOBALS['n'] = count($grid);

$GLOBALS['used'] = array();
for ($y = 0; $y < $GLOBALS['n']; $y++) {
    $GLOBALS['used'][$y] = array_fill(0, $GLOBALS['m'], false);
}

function calc($used) {
    $result = array('sum' => 0, 'grid_num' => 0);
    for ($x = 0; $x < $GLOBALS['m']; $x++) {
        for ($y = 0; $y < $GLOBALS['n']; $y++) {
            if ($GLOBALS['used'][$y][$x] == $used) {
                $result['sum'] += $GLOBALS['grid'][$y][$x];
                $result['grid_num']++;
            }
        }
    }
    return $result;
}

function search($x, $y, $sum1) {
    $GLOBALS['used'][$y][$x] = true;
   
    $rs = calc(false);
    if ($rs['sum'] == $sum1) {
        $new_answer = $GLOBALS['m'] * $GLOBALS['n'] - $rs['grid_num'];
        if ($GLOBALS['answer'] > $new_answer) {
            $GLOBALS['answer'] = $new_answer;
        }
        return;
    }
   
    $directions = array(array(-1, 0), array(0, -1), array(1, 0), array(0, 1));
    foreach ($directions as $dir) {
        $x_new = $x + $dir[0];
        $y_new = $y + $dir[1];
        if ($x_new >= 0 && $x_new < $GLOBALS['m'] && $y_new >= 0 && $y_new < $GLOBALS['n'] && !$GLOBALS['used'][$y_new][$x_new]) {
            $GLOBALS['used'][$y_new][$x_new] = true;
            search($x_new, $y_new, $sum1 + $GLOBALS['grid'][$y_new][$x_new]);
            $GLOBALS['used'][$y_new][$x_new] = false;
        }
    }
}
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>剪格子</title>
</head>

<body>
<?php
search(0, 0, $GLOBALS['grid'][0][0]);
echo '<b>结果: </b>';
if ($GLOBALS['answer'] == NO_ANSWER) {
    echo 0;
} else {
    echo $GLOBALS['answer'];
}
?>
</body>
</html>
一派护法 十九级
9楼 发表于:2016-5-23 19:52
运行结果:
结果: 10
一派护法 十九级
10楼 发表于:2016-5-23 19:53
【PHP面向对象版代码】
<?php
class grid {
    const NO_ANSWER = 0xffff;
   
    public $data = array();
    private $m;
    private $n;
    private $used;
    private $answer;
   
    public function add() {
        array_push($this->data, func_get_args());
    }
   
    public function calc_answer() {
        $this->answer = self::NO_ANSWER;
        if (isset($this->data[0])) {
            $this->m = count($this->data[0]);
            $this->n = count($this->data);
            $this->used = array();
            for ($y = 0; $y < $this->n; $y++) {
                $this->used[$y] = array_fill(0, $this->m, false);
            }
            $this->search(0, 0, $this->data[0][0]);
        }
        return $this->answer;
    }
   
    public function clear() {
        $this->data = array();
    }
   
    private function get_status($used) {
        $status = array('sum' => 0, 'grid_num' => 0);
        for ($x = 0; $x < $this->m; $x++) {
            for ($y = 0; $y < $this->n; $y++) {
                if ($this->used[$y][$x] == $used) {
                    $status['sum'] += $this->data[$y][$x];
                    $status['grid_num']++;
                }
            }
        }
        return $status;
    }
   
    private function search($x, $y, $sum) {
        $this->used[$y][$x] = true;
        $status = $this->get_status(false);
        if ($status['sum'] == $sum) {
            $new_answer = $this->m * $this->n - $status['grid_num'];
            if ($this->answer > $new_answer) {
                $this->answer = $new_answer;
            }
        } else {
            $directions = array(array(-1, 0), array(1, 0), array(0, -1), array(0, 1));
            foreach ($directions as $dir) {
                $x_new = $x + $dir[0];
                $y_new = $y + $dir[1];
                if ($x_new >= 0 && $x_new < $this->m && $y_new >= 0 && $y_new < $this->n && !$this->used[$y_new][$x_new]) {
                    $this->used[$y_new][$x_new] = true;
                    $this->search($x_new, $y_new, $sum + $this->data[$y_new][$x_new]);
                    $this->used[$y_new][$x_new] = false;
                }
            }
        }
    }
   
    public function show_answer() {
        $this->calc_answer();
        echo '<b>结果: </b>';
        if ($this->answer == self::NO_ANSWER) {
            echo 0;
        } else {
            echo $this->answer;
        }
        echo "<br>\n";
    }
}
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>剪格子</title>
</head>

<body>
<?php
$g = new grid();
$g->add(1, 1, 1, 1);
$g->add(1, 30, 80, 2);
$g->add(1, 1, 1, 100);
$g->show_answer();

$g->clear();
$g->add(10, 8, 5, 7, 6, 4);
$g->add(1, 9, 6, 2, 3, 5);
$g->add(1, 3, 2, 1, 5, 2);
$g->show_answer();

$h = new grid();
$h->add(10, 1, 52);
$h->add(20, 30, 1);
$h->add(1, 2, 3);
$h->show_answer();
?>
</body>
</html>

【运行结果】
结果: 10
结果: 6
结果: 3

回复帖子

内容:
用户名: 您目前是匿名发表
验证码:
(快捷键:Ctrl+Enter)
 

本帖信息

点击数:479 回复数:9
评论数: ?
作者:巨大八爪鱼
最后回复:巨大八爪鱼
最后回复时间:2016-5-23 19:53
 
©2010-2024 Arslanbar Ver2.0
除非另有声明,本站采用知识共享署名-相同方式共享 3.0 Unported许可协议进行许可。