| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2963 人关注过本帖
标题:商人过河问题,有兴趣的进来编个小程
只看楼主 加入收藏
墨清扬
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:1
帖 子:294
专家分:817
注 册:2011-10-4
收藏
得分:2 
……好久没写C了,好麻烦啊,在C++的环境下想尽可能地写得跟C一样,结果最后发现Bool不支持……所以以下代码请按C++编译
我还有一个问题,如果一侧只有仆人,合法么?我是按合法来处理
程序代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const int MAXN = 600;
const int MAXM = MAXN * MAXN * 2;
bool valid[2][MAXN][MAXN];

// A stat can represents a situation.
struct stat {
  // Number of businessman in the start bank.
  int bMan;
  // Number of servant in the start bank.
  int servant;
  // Whether current stat is in the start bank.
  bool start;
};

// A single step indicates how they moves.
struct step {
  int bMan;
  int servant;
};
stat stats[MAXM];
step steps[2][MAXN][MAXN];

// Whether a stats is valid.
bool isValid(const stat& s, int n) {
  int bMan = s.bMan, servant = s.servant;
  if(bMan < 0 || bMan > n || servant < 0 || servant > n) {
    return false;
  }
  if(bMan > 0 && servant > bMan) {
    return false;
  }
  if(bMan < n && n - servant > n - bMan) {
    return false;
  }
  return true;
}

// Tests for n businessmen and n servants whether there are ways to move safely.
bool test(int n) {
  int head = 0, tail = 0, i, j, bMan = n, servant = n, start = true;
  step currStep;
  stat tmp;
  // Initializes.
  memset(valid, 0, sizeof(valid));
  valid[start][bMan][servant] = true;
  stat curr;
  curr.bMan = bMan;
  curr.servant = servant;
  curr.start = start;
  stats[tail++] = curr;

  // BFS all possible status.
  while(head < tail) {
    curr = stats[head++];
    if(curr.bMan == 0 && curr.servant == 0 && !curr.start) {
      break;
    }
    for(i = 0; i <= 2; ++i) {
      for(j = i ? 0 : 1; i + j <= 2; ++j) {
        tmp = curr;
        tmp.start = !tmp.start;
        if(curr.start) {
          tmp.bMan -= i;
          tmp.servant -= j;
        } else {
          tmp.bMan += i;
          tmp.servant += j;
        }
        if(isValid(tmp, n)) {
          bMan = tmp.bMan;
          servant = tmp.servant;
          start = tmp.start;
          if(!valid[start][bMan][servant]) {
            currStep.bMan = i;
            currStep.servant = j;
            steps[start][bMan][servant] = currStep;
            stats[tail++] = tmp;
          }
          valid[start][bMan][servant] = true;
        }
      }
    }
  }
  return valid[0][0][0];
}

int main() {
  int n;
  int bMan = 0, servant = 0, start = false;
  step currStep;
  scanf("%d", &n);
  if(!test(n)) {
    printf("No\n");
    return 0;
  }
  printf("\tbMan\tservant\n");
  while(bMan != n || servant != n || !start) {
    currStep = steps[start][bMan][servant];
    printf("%s\t%d\t%d\n", start ? "Back" : "Go", currStep.bMan, currStep.servant);
    if(!start) {
      bMan += currStep.bMan;
      servant += currStep.servant;
    } else {
      bMan -= currStep.bMan;
      servant -= currStep.servant;
    }
    start = !start;
  }
  return 0;
}


[ 本帖最后由 墨清扬 于 2014-10-1 00:05 编辑 ]

酱油实习生
2014-10-01 00:03
pycansi
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:5
帖 子:418
专家分:1060
注 册:2012-7-26
收藏
得分:0 
谁能告诉我主仆的移动限制……自由上下船无解啊


莫问前尘有愧,但求今生无悔
2014-10-02 09:33
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
有点忙,先留一段代码上来,改天再解释里面每个数字的意义。
程序代码:
#include <stdio.h>

void show(int s)
{
    printf("{m:%d, s:%d} %s {m:%d, s:%d}\n",
        (s>>4)&3, (s>>1)&3, (s&1?"~!":"!~"),(s>>10)&3, (s>>7)&3);
}

int search(int * ss, int es)
{
    const int m[] = {0x7E,0xFC,0x3F0,0x7E0,0x46E};
    static char f[0x40];
    int s, c, t, i;

    if(*ss == es) return 1;
    f[*ss & 0x3F] = 1;
    for(i = 0; i < sizeof(m) / sizeof(m[0]); i++)
    {
        t = s = *ss + (*ss & 1 ? -m[i] : m[i]) ^ 1;
        if((t & 0x1248) != 0x1248) continue;
        t |= ((s >> 4 & 3) ? 0 : 0x30) | ((s >> 10 & 3) ? 0 : 0xC00);
        if(((t - ((t & 0x186) << 3)) & 0x1248) != 0x1248) continue;
        if(f[s & 0x3F]) continue;
        ss[1] = s;
        c = search(ss + 1, es);
        if(c > 0){ f[*ss & 0x3F] = 0; return c + 1;}
    }
    f[*ss & 0x3F] = 0;
    return 0;
}

int main()
{
    int ss[16] = {0x127E}, es = 0x1FC9, c, i;

    c = search(ss, es);
    for(i = 0; i < c; show(ss[i++]));
    return 0;
}

重剑无锋,大巧不工
2014-10-03 07:13
pycansi
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:5
帖 子:418
专家分:1060
注 册:2012-7-26
收藏
得分:0 
浅薄了,自由移动也可以有解,学习了


莫问前尘有愧,但求今生无悔
2014-10-03 09:41
邓士林
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:淮河河畔
等 级:贵宾
威 望:61
帖 子:2392
专家分:13384
注 册:2013-3-3
收藏
得分:0 
回复 23 楼 beyondyf
看不懂啊!为什么用十六进制啊

Maybe
2014-10-03 18:04
aha001
Rank: 1
等 级:新手上路
帖 子:3
专家分:2
注 册:2014-10-4
收藏
得分:2 
以下是引用pycansi在2014-9-30 10:55:45的发言:

欢迎 b版 重现江湖
 
也来凑个热闹,不过思索后发现这题$#!@阿....
比如 仆人划船,先运一个商人过去,然后只能再运仆人,但当仆人运到彼岸,船上两个仆人可以联合制服这个商人...
其他情况殊途同归...
 
此题如果想要有解,得把一个仆人给绑在船上....好黑暗的解题...不过正好契合黑暗的题目....
嗯 同意,强烈同意!!此题无解,除非船上的那一个人不算。。。否则都没有办法算!!
2014-10-04 15:44
pycansi
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:5
帖 子:418
专家分:1060
注 册:2012-7-26
收藏
得分:0 
回复 26 楼 aha001
诶,兄弟,我们都没考虑周全啊


莫问前尘有愧,但求今生无悔
2014-10-04 16:50
邓士林
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
来 自:淮河河畔
等 级:贵宾
威 望:61
帖 子:2392
专家分:13384
注 册:2013-3-3
收藏
得分:0 
在床上摆船的人应该不算,不然送到河对岸算一次,回来又算一次,这样三个人的时候都无解了

Maybe
2014-10-04 21:18
muyoucumian
Rank: 3Rank: 3
等 级:等待验证会员
帖 子:80
专家分:126
注 册:2014-8-30
收藏
得分:2 
把仆人用绳子把手脚绑起来,想怎么过河就怎么过河啦
2014-10-05 08:27
vvvcuu
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:12
帖 子:353
专家分:1253
注 册:2014-4-22
收藏
得分:0 
回复 25 楼 邓士林
代码为了加快执行速度或者为了保护知识产权等原因,经过了加密或者优化.

代码测试环境:  WinXP+C-Free5.0.
2014-10-05 11:34
快速回复:商人过河问题,有兴趣的进来编个小程
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.020396 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved