一開始真沒有想出來這道題幹怎麼做,後來看了乙個大神的解題思路,自己慢慢摸索出來了。
同樣做預處理,我們假設字串j加到字串i的前面,我們知道最優解的匹配肯定是,j的後面與i的前面做匹配,例如abcd和cdef,匹配出來就是abcdef,cd是j後面所擁有的,也是i前面所擁有的,這叫做加到i前面。
我們就可以列出來狀態轉移方程dp[j][s]=min(dp[i][s『]+cost[j][i])
這裡的dp就是j在最前面,並且有s狀態下的字串進行了匹配的時候。
自然s=s』|j<<1,即j不是這個狀態有的乙個字串,現在通過前面i在s』狀態的時候,加上這個時候j放在i前面匹配需要的代價,就是需要再在前面新增多少個字元。
最後重新建立字串,通過從最大開始遍歷最優解,相當於知道最優回溯的過程
#include
#include
#include
#include
#include
#include
#include
#define up(i,a,b) for(int i=a;i#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef
long
long ll;
const
double esp =
1e-6
;const
double pi =
acos(-
1.0)
;const
int inf =
0x3f3f3f3f
;using
namespace std;
int t;
int cost[18]
[18];
int dp[18]
[1<<18]
;int n;
string s[20]
;string res;
void
init()
}}//這裡先找到了萬一乙個串是另乙個的字串,直接去掉不要,對題目沒有一點影響
sort
(s, s+n)
; n =
unique
(s, s + n)
- s;
//因為unique只能對比最有兩邊的字串,所以先sort,排序一下剔除重複的。
up(i,
0, n)}}
}}//這個過程就是預處理cost的過程,靈活使用substr
}voidre(
int temp)}}
res +
= a;
s1^=(
1<< next)
;//每次去除已經新增的狀態
temp = next;}}
intmain()
if(n ==1)
//特例
init()
;//預處理
memset
(dp, inf,
sizeof
(dp));
//這裡求最小,把dp賦值成最大值
up(i,
0, n)
up(s,1,
(1<< n))}
}}}int temp =0;
up(i,
1, n)
//這裡是找到,狀態滿的時候,需要新增的最少字串的數目。
re(temp)
;//知道了最優解,還要找到最小的字串,通過遍歷最優解來得到
printf
("scenario #%d:\n"
, c)
; cout << res << endl << endl;
}return0;
}
P1795 無窮的序列
題目描述 有乙個無窮序列如下 110100100010000100000 請你找出這個無窮序列中指定位置上的數字 輸入格式 第一行乙個正整數n,表示詢問次數 接下來的n行每行乙個正整數ai,ai表示在序列中的位置。輸出格式 n行,每行為0或l,表示序列第ai位上的數字。輸入輸出樣例 輸入 1 431...
hrbust 1795發現王國之旅 最小生成樹
發現王國之旅 time limit 1000 ms memory limit 32768 k total submit 30 17 users total accepted 17 15 users rating special judge no description 暑期將至,壯壯和胖胖約定去 發...
POJ 1753 POJ 2965 解題報告
poj 1753 poj 2965 解題報告 poj 1753 和 poj 2965 是同一型別的題目,但是2965 有乙個比較簡單的方法來解決。poj 1753 我用的是打表的方法,打表很不厚道。思路 首先我們需要確定儲存的資料結構,從網上搜得用二進位制位來存,這確實是個很巧妙的方法,例如,我們將...