POJ 1795 又是通過方程找回去最優解的題目

2021-09-11 05:23:03 字數 1974 閱讀 6259

一開始真沒有想出來這道題幹怎麼做,後來看了乙個大神的解題思路,自己慢慢摸索出來了。

同樣做預處理,我們假設字串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 我用的是打表的方法,打表很不厚道。思路 首先我們需要確定儲存的資料結構,從網上搜得用二進位制位來存,這確實是個很巧妙的方法,例如,我們將...