論壇中我的總結:這題就是個狀壓dp,我們設:這題用狀壓dp實現。
我們先對於起點和終點,以及朋友家每個跑一遍spfa,將這些點定義為關鍵點,兩兩之間都求出了最短路,然後我們可以用狀壓dp來解決問題。
我們可以設f[i][j]表示當前到達點i,走過朋友家的狀態為j的最短路。這是從1到n的!
然後我們再設g[i][j]表示當前到達點j,走過朋友家的狀態為j的最短路。這是從n到1的!
而f的初始值為:f[0][0]=0;(0表示起點,k+1表示終點)
g的初始值為:g[k+1]=f[k+1];
最後的答案在g[0]中找即可。
做完f後就把f[k]賦值為g[k],然後在照做一遍就可以了。
我們可以將第0個朋友表示為1,第k+1個朋友表示為n。
上標:
#include
#include
#include
#define n 10010
#define m 50010
#define ll long long
using namespace std;
struct nodee[m<<2]
;int n,m,k,t,tail[n]
,cnt=
0,f[n<<3]
,fd[17]
,x,ans=0;
ll d[n]
,dis[17]
[17],f[17]
[70010
],g[17]
[70010
],time;
bool bz[n]
;inline
intread()
inline
void
add(
int u,
int v,
int l)
; tail[u]
=cnt;
}void
spfa
(int x)
bz[f[l]]=
0;}}
intchange
(int x)
intmain()
for(
int i=
1;i<=k;i++
) fd[i]
=read()
; fd[0]
=1;fd[
++k]
=n;for
(int i=
0;i<=k;i++)/*
for (int i=0;i<=k;i++)
*/memset
(f,60
,sizeof
(f))
;f[0][
0]=0
;for
(int j=
0;j<=(1
<;j++
)for
(int i=
0;i<=k;i++)}
memset
(g,60
,sizeof
(g))
;for
(int i=
0;i<=(1
<;i++
) g[k]
[i]=f[k]
[i];
for(
int j=
0;j<=(1
<;j++
)for
(int i=k;i>=
0;i--)}
for(
int i=
0;i<=(1
<;i++)if
(g[0
][i]
<=t)
if(ans==0)
puts
("-1");
else
printf
("%d %lld\n"
,ans-
1,time)
;return0;
}
NOIP2014模擬11 1B組 吳傳之火燒連營
trie,動態開點。我們可以將輸入的a,b全部看成二進位制數。然後按照二進位制中的位置從大到小開始建trie。如果trie不會的可以自己手動普及一下。建好a的trie後,我們可以對於每個b i 開始求答案。答案可以說是貪心來求的。正確性可以保證。如果對於當前結點 1 只有乙個兒子,那就走那乙個兒子。...
NOIP2014模擬11 1B組 吳傳之火燒連營
trie,動態開點。我們可以將輸入的a,b全部看成二進位制數。然後按照二進位制中的位置從大到小開始建trie。如果trie不會的可以自己手動普及一下。建好a的trie後,我們可以對於每個b i 開始求答案。答案可以說是貪心來求的。正確性可以保證。如果對於當前結點 1 只有乙個兒子,那就走那乙個兒子。...
NOIP2014提高組模擬題 8 9
一 最大配對 題意 給兩個序列,要求選k組,每組從兩個序列中各選乙個數,要使各組數的差的和最大。小論 兩個序列分別排序。每次用乙個序列的最大的減另乙個序列的最小的。當時情況 估計100分,結果50分。雖然題目有提醒答案可能超過2 31 1,我也看到了,但想著等下打完再改,於是我打著打著就忘了 最後掛...