Description

Those who have see the film of "Kong Fu Panda" must be impressive when Po opens the dragon scroll, because nothing was recorded on it! Po was surprising at the situation; Tai Lung and Master Shifu were also surprising since no body believes that the mystic dragon scroll is just a blank paper. After Tai Lung was defeated, Po found Master Wugui’s Diary and know that the dragon scroll recorded some messages long long years ago, but these messages were blurred due to abrasions. Master Wugui has copied these blurred messages and he wants someone to recover these messages. The messages has a specific length, and each position could be digit, '?' or ','. It is known that each message recorded some strictly increasing positive integers (without leading zeroes) separated by commas and Po is asked to recover these numbers.

Input

There are multiple test cases. Each test case contains string in a line represented. The length of the string will not exceed \(500\). The format is shown in the sample input.

Output

If the message has no appropriate solution, print "impossible", else print the decrypted message. If there exists multiple solutions, output the one whose first number is the smallest; if there is a tie, output the one whose second number is the smallest; and so on.

Sample Input

?,10,?????????????????,16,??

?2?5??7?,??

???????????????????????????????,???

Sample Output

impossible

12,50,70,71

1,2,3,4,5,6,7,8,9,10,11,100,101,102

这个题目dp应该很好想,然后就是难得写。

我们用\(f_i\)表示从\(i\)这个位置开始的合法序列第一个数字最大是多少。然后很容易想到dp来求\(f_i\)。

\[f_i = maxconvert(i,j,j+2)
\]

这个\(maxconvert\)的意思是在\([i,j]\)中填数字,\(j+1\)上填',',构造出比\(f_{j+2}\)小最大的数字是多少。

然后这个\(maxconvert\)写起来有些日狗。

我们将\(S_i \sim S_j\)记作\(S\),将\(f_{j+2}\)记作\(pat\)。

我们抓住这一点——我们肯定是要找到最后大的\(id\),使得\(S_1 \sim S_{id-1} = pat_1 \sim pat_{id-1}\),然后\(S_{id} < pat_{id}\),且\(S_{id}\)要填满足的最大值。\(S_{id+1} \sim\)的'?'全部换成'9'。

之后有了\(f\),我们就可以判断有无解了。

但是还要输方案,我们可以采用贪心的思想,每次都填最小的。假设我们已经填好了\(1 \sim i\),要在\(i+2 \sim j\)中填上数字,我们只要保证填的数字小于\(f_{j+2}\)即可。我们可以构造一个\(minconvert(i,j,j+2)\)函数,表示在\([i,j]\)中填数字,使得填出来的数字比\(S_1 \sim S_j-1\)的数字中的最大值大的最小值是多少。当然要保证此数字小于\(f_{j+2}\)。然后这题就做完了。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std; const int maxn = 510;
char S[maxn]; int N;
struct Node
{
char s[maxn]; int len;
friend inline bool operator <(const Node &a,const Node &b)
{
if (a.len != b.len) return a.len < b.len;
for (int i = 0;i < a.len;++i) if (a.s[i] != b.s[i]) return a.s[i] < b.s[i];
return 0;
}
inline Node &operator=(const Node &a)
{
if (this == &a) return *this;
len = a.len;
for (int i = 0;i < len;++i) s[i] = a.s[i]; s[len] = 0;
return *this;
}
inline Node():len(0) { s[len] = 0; }
}f[maxn],now; inline void maxconvert(int x,int y,const Node &z)
{
if (y+2 < N&&y-x+1 > z.len) return;//位数多了,gg Node tmp;
if (y+2 >= N||y-x+1 < z.len)
{
for (int i = x;i <= y;++i) tmp.s[tmp.len++] = (S[i] == '?'?'9':S[i]);
if (tmp.s[0] != '0') f[x] = tmp;
return;
}//位数少了,补9 int id = -1; //位数一样
for (int i = x;i <= y;++i)
{
if (S[i] == z.s[i-x]) continue;
if (S[i] != '?'&&S[i] > z.s[i-x]) { if (id != -1) break; return; }
if (S[i] == '?'&&z.s[i-x] == '0') continue;
if (S[i] == '?'&&z.s[i-x] == '1'&&i == x) continue;
id = i;
if (S[i] != '?'&&S[i] < z.s[i-x]) break;
}
if (id == -1) return;
for (int i = x;i < id;++i) tmp.s[tmp.len++] = z.s[i-x];
if (S[id] == '?') tmp.s[tmp.len++] = z.s[id-x]-1;
else tmp.s[tmp.len++] = S[id];
for (int i = id+1;i <= y;++i) tmp.s[tmp.len++] = (S[i] == '?'?'9':S[i]);
if (tmp.s[0] != '0') f[x] = tmp;
} inline bool minconvert(int x,int y,const Node &z)
{
if (y-x+1 < now.len) return false;//位数多了,gg
Node tmp;
if (y-x+1 > now.len)
{
tmp.s[tmp.len++] = (S[x] == '?'?'1':S[x]);
for (int i = x+1;i <= y;++i) tmp.s[tmp.len++] = (S[i] == '?'?'0':S[i]);
if (tmp.s[0] != '0'&&(y+1 >= N||tmp < z))
{
for (int i = x;i <= y;++i) S[i] = tmp.s[i-x];
now = tmp; return true;
}
return false;
}
int id = -1;
for (int i = x;i <= y;++i)
{
if (now.s[i-x] == S[i]) continue;
if (S[i] != '?'&&S[i] < now.s[i-x]) { if (id != -1) break; return false; }
if (S[i] == '?'&&now.s[i-x] == '9') continue;
id = i;
if (S[i] != '?'&&S[i] > now.s[i-x]) break;
}
if (id == -1) return false; for (int i = x;i < id;++i) tmp.s[tmp.len++] = now.s[i-x];
if (S[id] == '?') tmp.s[tmp.len++] = now.s[id-x]+1;
else tmp.s[tmp.len++] = S[id]; for (int i = id+1;i <= y;++i) tmp.s[tmp.len++] = (S[i] == '?'?'0':S[i]);
if (tmp.s[0] != '0'&&(y+1 >= N||tmp < z))
{
for (int i = x;i <= y;++i) S[i] = tmp.s[i-x];
now = tmp; return true;
}
return false;
} int main()
{
freopen("3717.in","r",stdin);
freopen("3717.out","w",stdout);
while (scanf("%s",S) != EOF)
{
N = strlen(S);
for (int i = 0;i < N+10;++i) f[i].len = 0; for (int i = N-1;i >= 0;--i)
{
if (S[i] == ',') continue;
for (int j = i;j < N;++j)
{
if (j+1 >= N||S[j+1] == ','||(S[j+1] == '?'&&j+2 < N&&S[j+2] != ','))
{
maxconvert(i,j,f[j+2]);
if (S[j+1] == ',') break;
}
}
} now.len = 0; bool fnd = true;
for (int i = 0;i < N;++i)
{
if (S[i] == ',') continue;
bool succ = false;
for (int j = i;j < N;++j)
if (j+1 >= N||S[j+1] == ','||(S[j+1] == '?'&&j+2 < N&&S[j+2] != ','))
{
if (minconvert(i,j,f[j+2]))
{
if (S[j+1] == '?') S[j+1] = ',';
succ = true; i = j; break;
}
if (S[j+1] == ',') break;
}
if (!succ) { fnd = false; break; }
}
if (!fnd) puts("impossible");
else puts(S);
}
fclose(stdin); fclose(stdout);
return 0;
}

POJ3717 Decrypt the Dragon Scroll的更多相关文章

  1. 【构建Android缓存模块】(一)吐槽与原理分析

    http://my.oschina.net/ryanhoo/blog/93285 摘要:在我翻译的Google官方系列教程中,Bitmap系列由浅入深地介绍了如何正确的解码Bitmap,异步线程操作以 ...

  2. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  3. FC红白机游戏列表(维基百科)

    1055个fc游戏列表 日文名 中文译名 英文版名 发行日期 发行商 ドンキーコング 大金刚 Donkey Kong 1983年7月15日 任天堂 ドンキーコングJR. 大金刚Jr. Donkey K ...

  4. [转]Decrypt Any iOS Firmware on Mac, Windows, Linux

    source:http://www.ifans.com/forums/threads/decrypt-any-ios-firmware-on-mac-windows-linux.354206/ Dec ...

  5. how to use fiddler and wireshark to decrypt ssl

    原文地址: http://security14.blogspot.jp/2010/07/how-to-use-fiddler-and-wireshark-to.html Requirements2 C ...

  6. 【前端性能】高性能滚动 scroll 及页面渲染优化

    最近在研究页面渲染及web动画的性能问题,以及拜读<CSS SECRET>(CSS揭秘)这本大作. 本文主要想谈谈页面优化之滚动优化. 主要内容包括了为何需要优化滚动事件,滚动与页面渲染的 ...

  7. MUI开发APP,scroll组件,运用到区域滚动

    最近在开发APP的过程中,遇到一个问题,就是内容有一个固定的头部和底部.         头部就是我们常用的header了,底部的话,就放置一个button,用来提交页面数据或者进入下一个页面等,效果 ...

  8. 翻唱曲练习:龙珠改主题曲 【Dragon Soul】龙之魂

    首先这是个人翻唱曲: 这个是原版(燃): 伴奏:  翻唱合成为动漫AMV 出镜翻唱: 全民K歌链接: http://kg.qq.com/node/play?s=aYpbMWb6UwoU&g_f ...

  9. 完美解决,浏览器下拉显示网址问题 | 完美解决,使用原生 scroll 写下拉刷新

    在 web 开发过程中我们经常遇到,不想让用户下拉看到我的地址,也有时候在 div 中没有惯性滚动,就此也出了 iScroll 这种关于滚动条的框架,但是就为了一个体验去使用一个框架好像又不值得,今天 ...

随机推荐

  1. lintcode_177_把排序数组转换为高度最小的二叉搜索树

    把排序数组转换为高度最小的二叉搜索树   描述 笔记 数据 评测 给一个排序数组(从小到大),将其转换为一棵高度最小的排序二叉树. 注意事项 There may exist multiple vali ...

  2. Integer和int使用==比较的总结

    public static void main(String[] args) { int i1 = 128; Integer i2 = 128; Integer i3 = new Integer(12 ...

  3. Dapper and Repository Pattern in MVC

    大家好,首先原谅我标题是英文的,因为我想不出好的中文标题. 这里我个人写了一个Dapper.net 的Repository模式的底层基础框架. 涉及内容: Dapper.net结合Repository ...

  4. 怎样通过互联网ssh访问家里电脑

    需求:用可以上网的公司windows电脑连接家里的manjaro linux电脑.. 环境情况:公司电脑为内网,通过登录出口服务器连接互联网.家里的电脑也为内网,通过连接无线路由器连接外网.路由器有公 ...

  5. C语言基础篇(二)运算符

    导航: 2.1 算数运算符 2.2 逻辑运算符 2.3 位运算 2.4 赋值运算 2.5 内存访问符号 ----->x<------------->x<------------ ...

  6. emplace_back

    c++11 的 list deque 和 vector 增加了emplace_back函数,相对于push_back函数,它减少了一次类的构造,因此效率更高,推荐使用. #include <li ...

  7. ORA-01122: 数据库文件 1 验证失败

    1.SQL>shutdown abort 如果数据库是打开状态,强行关闭 2.SQL>sqlplus / as sysdba 3.SQL>startupORACLE 例程已经启动. ...

  8. PHP.30-TP框架商城应用实例-后台6-商品会员价格删除-外键,级联操作

    商品会员价格删除 需求:当删除一件商品时,这件商品对应的会员价格也应该从会员价格表{price,level_id,goods_id}中删除掉. 有两种删除方法 1.在钩子函数_before_delet ...

  9. 3 web框架

    web框架 Web框架(Web framework)是一种开发框架,用来支持动态网站.网络应用和网络服务的开发.这大多数的web框架提供了一套开发和部署网站的方式,也为web行为提供了一套通用的方法. ...

  10. 2,版本控制git --分支

    有人把 Git 的分支模型称为它的`‘必杀技特性’',也正因为这一特性,使得 Git 从众多版本控制系统中脱颖而出. 为何 Git 的分支模型如此出众呢? Git 处理分支的方式可谓是难以置信的轻量, ...