DP套題練習3

2022-08-21 05:18:11 字數 3869 閱讀 9636

t1:火車站內往往設有一些主幹線分叉出去的鐵路支路,供火車停靠,以便上下客或裝載貨物鐵路支路有一定長度;火車也有一定的長度,且每列火車的長度相等.假設某東西向的鐵路上,有一小站.該站只有一條鐵路支路可供火車停靠,並且該鐵路支路最多能容納 m 輛火車為了火車行駛的通暢,該站只允許火車自東方進站,自西方出站,且先進站的火車必須先出站,否則,站內火車將發生堵塞該火車站工作任務繁忙.每天都有 n 輛自東方駛向西方的火車要求在預定時刻進站,並在站內作一定時間的停靠.為了滿足每輛進站火車的要求,小站的排程工作是井井有條地開展.在小站每天的工作開始前,小站工作人員須閱讀所有火車的進站申請,並決定究競接受哪些火車的申請.而對於不能滿足要求的火車,小站必須提前通知它們,請它們改變行車路線,以免影響正常的鐵路運輸工作.由於火車進站、出站的用時可以忽略不計,小站允許幾輛火車同時進站或出站,且小站工作人員可以任意安排這些火車進站的先後排列次序.小站的工作原則是盡量地滿足申請火車的要求請你編乙個程式,幫助工作人員考察某天所有火車的進站申請,計算最多能滿足多少火車的要求.

s1:顯然當m=1時就是貪心決策的"活動安排".要總結一下對於區間問題,不要隨意用[ 0/1 ]表示選不選,可能是本人太菜了,這樣推只成功過一次.回歸本題,我們按進站時間sort(如果進站時間相同則按出站時間排序),再分m=1/2/3來討論.當m=1時,可以貪心,也可dp.我們設f [ i ]表以第 i 輛車開頭能合法最長車輛個數,顯然f[ i ]=max(len[ j ].l>len[ i ].r),注意初始化f[ i ]=1.當m = 2,我們用f[ i ][ j ]表示以第 i輛為第 1 輛車,第 j 輛為第 2 輛車為開頭能合法最長的車輛個數,f[ i ][ j ]=max,這時注意i,j,k要保證i,j,k先進先出且k要等i出站再進站.當m = 3,f[ i ][ j ][ k ]=max注意i, j,k先進先出,j,k,g先進先出,且g在i出站後進站.以集合結尾幾個元素代表集合可以聯絡練習t3.

#include#include

#include

#include

using

namespace

std;

#define re register

int n,m,f1[101],f2[101][101],f3[101][101][101

];struct

bianlen[

110];

bool

cmp(bian a,bian b)

void

work1()

printf("%d

",ans);

}void

work2()

}printf("%d

",ans);

}void

work3()

}printf("%d

",ans);

}int

main()

else

if(m==2)

else

return0;

}

t2:給定一具有 n 個頂點(從 1 到 n 編號)的凸多邊形,每個頂點的權均已知。問如何把這個凸多邊形劃分成 n-2 個互不相交的三角形,使得這些三角形頂點的權的乘積之和最小.

s2:顯然的區間dp,由小區間的最值推大區間的最值.但有一點麻煩的是如果我們設f[ i ][ j ]代表區間[ i , j ]點最成多邊形的乘積之和最小,在列舉分割點k時我們發現無法用f[ i ][ j ]去表示不是連續點組成的多邊形(如①③④組成的三角形),自己還想用map求判斷每種多邊形,顯然這樣n!數量要爆long long的.看了題解方程f[ i ][ j ]=min(f[ i ][ k ]+f[ k ][ j ]+val[ i ]*val[ j ]*val[ k ]).發現這樣轉移能巧妙地將無法表示的多邊形直接計算出來,差了轉換的思想.

#include#include

#include

using

namespace

std;

#define e exit(0)

#define re register

#define ll long long

long

long n,val[110],f[110][110

];long

long getv(ll x,ll y,ll z)

intmain()

printf(

"%lld

",f[1

][n]);

return0;

}

t3:加分二叉樹

s3:我們會發現對於區間[ i , j ],根結點k是決定同一中序不同形態樹的關鍵.我們設f[ i ][ j ]表示區間[ i, j ]最高加分.我們列舉根節點k,f[ i ][  j ]=max,注意k要討論i,j兩個端點情況.再用root陣列記錄轉移關鍵點,記錄區間根節點.我們不斷遞迴區間根據根節點建樹,在進行前序遍歷即可.

#include#include

#include

using

namespace

std;

#define e exit(0)

#define re register

#define ll long long

long

long n,s,val[110],vis[110],f[110][110],root[110][110

];struct

shutree[

110*2

];void

add(ll fa,ll son,ll flag)

ll build(ll l,ll r)

else

if(s==l)

else

if(s==r)

else

}void

dlr(ll x)

intmain()

for(re ll len=2;len<=n;++len)

for(re ll i=1;i+len-1

<=n;++i)

for(re ll len=2;len<=n;++len)

for(re ll i=1;i+len-1

<=n;++i)

}printf(

"%lld\n

",f[1

][n]);

s=build(1

,n);

dlr(s);

return0;

}

t4:最長字首

s4:dp水題.f[ i ]表示能不能用字串組成前 i 個字元.這樣我們對每個 長度i往前推已知的字元長度len,如果f[ i - len ]合法則繼承更新.

#include#include

#include

using

namespace

std;

#define e exit(0)

#define r register

string s[110

];char t[500010

];int n,lent,flag,lens[110],f[500010

];int

main()

scanf("%s

",t+1

); lent=strlen(t+1

); --lent;

f[0]=1

;

for(r int i=1;i<=lent;++i)

++sur;

}if(flag)}}

for(r int i=lent;i>=1;--i)

if(f[i])

printf("0

");return0;

}

DP 套 DP 與動態 DP

即對於某種過程,我們需要 dp 進行,如果我們要對這個 dp 過程還要計數或者做其他的事,這時候我們需要對每一種 dp 的狀態都記錄下其對應的值,作為計數 dp 的狀態。例題 cf578d cf979e cf1229e2 對於某種 dp 過程,我們可能需要修改這個 dp 中間的某些常數。通常情況下這...

BNUZ套題比賽div3

solution 題意 給定n個座位要求 沒有鄰座的鄰居並且在此前提下在增加乙個座位是不可能的。1 表示已佔座,0 表示空位,符合情況輸出 yes 否則輸出 no 滿足情況的有 1 的旁邊沒有 1 和 沒有 000 的情況 題解 include int main else else if s i 0...

USACO 狀壓DP練習 3

1725 題意 m n m,n le 12 的牧場,有的格仔不能選,相鄰不能同時選,求方案數 f i j 前 i 行當前行選的集合為 j include include include include include using namespace std typedef long long ll ...