UVa1024

摘要:
//UVA1204主题:一些孩子在一个圆圈里玩游戏。每个手帕上的数字不得超过100。第二个是考虑花园端到端连接的特点。因此,在处理花园时,我们需要考虑结尾和开头之间的重叠。因此,我们需要知道第一个序列在这个状态下的位置。似乎可以在不添加维度的情况下进行处理。然后,我们需要考虑输入字符串是否可能是圆的一部分,而是在许多圆之后的结果。这是否会影响以及如何执行取决于代码,然后,如果计算结果为1,我们需要输出2mentation://UVa1204#include#include#include#include#includeusingspacestd#defineREP(i,n)forconstintmaxn=16;intcalc_overlap{intn1=a.length();intn2=b.length(;for{ifcontinue;boolok=true;forif(a[j+i]!

// UVa 1204
题意:一些小孩(至少是两个)围成一圈做游戏。每一轮从某个小孩开始往他左边或右边传手帕。
一个小孩拿到手帕后(包括第一个小孩)在手帕上写下自己的性别,男孩写B,女孩写G,
然后按相同的方向传给下一个小孩,每一轮可能在任何一个小孩写完后停止。
现在游戏已经进行了n轮,已知n轮中每轮手帕上留下的字,求最少有几个小孩。
每轮手帕上的数字不超过100。
2 <= n <= 16

思路:我们可以将问题进行简化,将圈先转化成一条线,
然后解决线上面的动态规划,然后将它转换成圈。
对于线上的问题,我们要寻找出最短的序列,使之序列包含上述n个子序列,
那么对于k序列我们想要插入上述序列,与k序列有关系的只有k前面的序列(k插入位置的前面那个序列)
所以我们的状态要包含最后一个序列是什么,然后我们的状态需要包含在不同范围(i-j)中的最有解是什么,
然后逐步扩大范围,最后输出全集(1-n)的最有解即可,所以我们的状态一定要包含一个集合,对于2<=n<=16
来说,这个范围刚好(不大不小,可以将集合表示出来),所以可以得到最终的状态的定义:
d(s,j)表示s集合其中j元素为结尾的最短序列。
其次就是状态转移方程:
d(s,j) = min(d(s-{j}, i)+t(j)-both(i,j)) (其中both(i,j)表示以i为头以j为尾的公共部分)
然后采用递推的方法将集合枚举的越来越大,然后求解,一共有(n*2^n)中状态,每个状态有(n)种决策方式,
所以时间复杂度为O(n^2*2^n)
下面来说一说将线(或行)转化成圈的过程吧!
(1)原题说了可以顺时针也可以逆时针,这在上面处理线时并没有考虑,每个状态d(i,j)有2n中可能,决策数也变成2n,
这仅仅是常数的变换,所以时间复杂度并没有改变,在处理时我们要考虑是正过来"粘"还是倒过来"粘"。
(2)其次就是考虑园首尾相连的特征,所以我们在进行,处理园的时候要考虑结尾与开头之间的重叠部分,
所以需要知道这个状态第一个序列的摆放位置,好像不必增加维度就能够处理(那一定是状态定义上的"约束"了),
然后考虑输入字符串可能是不是圈的一部分,而是绕了很多圈以后的结果,这个会不会影响以及怎么做就需要看代码了,
然后对于如果算出的结果为1的话,我们需要输出2。
后面就是代码实现了,下面可能说代码处理的问题(也可能不)。
补充(代码处理以及忘了说的地方)
1.如何处理首位接应的问题,我想了想,还是增加一位来记录第一个序列是什么,但是不用确定第一个序列的方向(或是说,只需要
一个方向就行,所以代码上我只规定了正方向)(这样不会丢失最优解,想一想,为什么?)。
2.然后就是将之间的东西进行简化,我说一说输入,如果给的两个序列i,j其中i∈j(竟然会了打数学符号,哈哈),那么我们
不需要考虑i,想一想为什么,这样简化问题能够促使我们想出一些思路的。
通过编写带代码,我发现了几个自己并不能够实现的问题,下面说一说问题与lrj的解决思路:
1、如何判断输入的两个序列中其中一个包含另一个? 使用stl的string中的find函数。
2、为什么可以不需要增加一维来记录开始的部分? 任选一个序列的正方向作为开头就行。(这样也不会丢失最优解?想一想,为什么?)
3、对于一个序列可能绕了几圈怎么解决? 这个会在最后末尾"粘贴"到头的时候有所体现(这个我想的也不太清楚)。
下面是代码实现:

// UVa 1204
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;

#define REP(i,n) for (int i = 0; i < (n); ++i)

const int maxn = 16;

int calc_overlap(const string& a, const string& b) {
  int n1 = a.length();
  int n2 = b.length();
  for (int i = 1; i < n1; ++i) {
         if (n2+i <= n1) continue;
         bool ok = true;  
         for (int j = 0; j+i < n1; ++j)
           if (a[j+i] != b[j]) { ok = false; break; }
         if (ok) return n1-i;   
  }
  return 0;
}

struct Seq {
  string s, rev;
  bool operator < (const Seq& rhs) const {
    return s.length() < rhs.s.length();
  }
} seq[maxn];

int n;
string new_seq[maxn][2];
int len[maxn];
int overlap[maxn][maxn][2][2];

void init() {
    REP(i, n) {
    cin >> seq[i].s;
    seq[i].rev = seq[i].s;
    reverse(seq[i].rev.begin(), seq[i].rev.end());
  }
  int n2 = 0;
  sort(seq, seq+n);  
  REP(i, n) {
    bool need = true;  
    for (int j = i+1; j < n; ++j) {
        if (seq[j].s.find(seq[i].s) != string::npos ||
            seq[j].rev.find(seq[i].s) != string::npos) { need = false; break; }
    }
    if (need) {
            new_seq[n2][0] = seq[i].s; new_seq[n2][1] = seq[i].rev;
            len[n2] = seq[i].s.length();
            n2++;
    }
    }
    n = n2;
    REP(i, n) REP(j, n) REP(x, 2) REP(y, 2)
          overlap[i][j][x][y] = calc_overlap(new_seq[i][x], new_seq[j][y]);
}

int d[1<<maxn][maxn][2];

void update(int& x, int v) {
  if (x < 0 || v < x) x = v;
}

void solve() {
    memset(d, -1, sizeof(d));
    d[1][0][0] = len[0];
    int full = (1<<n)-1;
    for (int s = 1; s < full; ++s)
      REP(i, n) REP(x, 2) if (d[s][i][x] >= 0)
          for (int j = 1; j < n; ++j)
            if (!(s&(1<<j)))
              REP(y, 2) update(d[s|(1<<j)][j][y], d[s][i][x]+len[j]-overlap[i][j][x][y]);
  int ans = -1;
  REP(i, n) REP(x, 2) {
    if (d[full][i][x] < 0) continue;
    update(ans, d[full][i][x]-overlap[i][0][x][0]);
  }
  if (ans <= 1) ans = 2;
  printf("%d
", ans);
}

int main() {
  while (scanf("%d", &n) == 1 && n) {
    init();
    solve();
  }
  return 0;
} 

免责声明:文章转载自《UVa1024》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇vue 图片转base 64sharepoint:苹果设备访问设置(包括打开infopath表单) 金大昊(jindahao)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

如何在jenkins上新建一个项目及其简单配置

单击[新建]进入选择页面,您可以在此页面上配置项目(包括拉取源代码、修改连续构建时间以及在打包和部署之前修改配置文件)3。在General中,您可以设置要构建的版本,如下图5所示。在源代码管理模块中,您可以设置源代码地址(我们公司常用的Git)6。如果是自动构建,您可以将自动构建时间(即构建频率)设置为7。以下是构建中的一些设置。您可以使用shell修改源代...

微信支付服务商模式支付与普通微信支付的配置区别

chapter=7_7&index=5注:与普通微信支付相比,源代码是上述7/8之间的区别,其他可以看作是服务提供商自己的微信支付配置;...

mac格式化重装系统

4.选择“重新安装MacOS”5.按照以下步骤中的提示进行操作。安装需要半个多小时。在此期间无法断开网络,否则需要重新安装...

Django如何安装指定版本

Django的最新版本默认安装为:pipinstalldjangoDjango,然后是版本号:pipinstalldjango==1.11.7如果使用pipinstall库的安装速度较慢,您可以使用豆瓣的图片:pipinstalldjango==1.11.7-ihttp://pypi.douban.com/simple--trusted-hostpypi.d...

前端导航站点(PC端)

本篇LIST1.项目预览地址:项目预览地址2.项目完成效果:3.HTML布局拆分1.tip提示部分2.title标题部分3.搜索栏部分找的是codepen上现成的搜索框样式,包含搜索框展开收缩的特效。...

uniapp 实现动态切换全局主题色

要求:要在开发的应用程序中切换主题颜色,如果只需要一种主题颜色,但不需要切换,则可以使用uniappSCSS文件文档思想:预先在公共css中定义所需的主题颜色。这里只是一个定义两种颜色的参考文档的示例,可以从中获得想法。您可以使用css属性选择器动态设置数据xx以动态更改主题颜色。最初,您希望将一个变量直接混合到mixin中,以实现主题颜色的全局控制,忽略了...