由於天梯賽不能帶模板,對於我這種模板嚴重依賴患者是很難受的,又因爲去年打那麼菜,今年題目不是太難的話怎麼着也得上200呀,所以來重新打一遍模板,交一下裸題驗證其正確性。
需要準備的也不是太多,主要是一些基本的圖論算法以及dp。畢竟都是理解了的,應該不會耗時很久。
就按照白書上面的順序來敲吧。
一、01揹包
二維的:
int dp[maxn][maxn];
int w[maxn], v[maxn];
int main()
{
int t; scanf("%d", &t);
while(t--){
memset(dp, 0, sizeof(dp));
int n, V; scanf("%d %d", &n, &V);
rep(i, 1, n) scanf("%d", v + i);
rep(i, 1, n) scanf("%d", w + i);
rep(i, 1, n){
rep(j, 0, V){
if(w[i] > j) dp[i][j] = dp[i-1][j];
else dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i]);
}
}
printf("%d\n", dp[n][V]);
}
return 0;
}
一維的:
int dp[maxn];
int w[maxn], v[maxn];
int main()
{
int t; scanf("%d", &t);
while(t--){
memset(dp, 0, sizeof(dp));
int n, V; scanf("%d %d", &n, &V);
rep(i, 1, n) scanf("%d", v + i);
rep(i, 1, n) scanf("%d", w + i);
rep(i, 1, n){
Rep(j, V, w[i]){
dp[j] = max(dp[j], dp[j-w[i]] + v[i]);
}
}
printf("%d\n", dp[V]);
}
return 0;
}
二、LCS問題
char s[maxn], t[maxn];
int dp[maxn][maxn];
int main()
{
while(~scanf(" %s %s", s + 1, t + 1)){
memset(dp, 0, sizeof(dp));
int n = strlen(s + 1), m = strlen(t + 1);
rep(i, 1, n){
rep(j, 1, m){
if(s[i] == t[j]) dp[i][j] = dp[i-1][j-1] + 1;
else dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
printf("%d\n", dp[n][m]);
}
return 0;
}
三、完全揹包問題
題目:Piggy-Bank
直接一維吧:
int w[505], v[505];
int dp[10005];
int main()
{
int t; scanf("%d", &t);
while(t--){
int e, f; scanf("%d %d", &e, &f);
int V = f - e;
rep(i, 0, V) dp[i] = inf;
int n; scanf("%d", &n);
rep(i, 1, n) scanf("%d %d", v + i, w + i);
dp[0] = 0;
rep(i, 1, n){
rep(j, w[i], V){
dp[j] = min(dp[j], dp[j-w[i]] + v[i]);
}
}
if(dp[V] == inf) puts("This is impossible.");
else printf("The minimum amount of money in the piggy-bank is %d.\n", dp[V]);
}
return 0;
}
四、多重部分和問題
題目:Dividing
int a[10] = {0, 1, 2, 3, 4, 5, 6 }, m[10];
int dp[maxn];
int main()
{
int cnt = 0;
while(~scanf("%d", m + 1)){
rep(i, 2, 6) scanf("%d", m + i);
bool f = 0;
rep(i, 1, 6) if(m[i]) f = 1;
if(!f) break;
printf("Collection #%d:\n", ++cnt);
int sum = 0;
rep(i, 1, 6){
sum += i * m[i];
}
if(sum & 1) { puts("Can't be divided.\n"); continue; }
sum /= 2;
fill(dp, dp + sum + 1, -1);
dp[0] = 0;
rep(i, 1, 6){
rep(j, 0, sum){
if(dp[j] >= 0) dp[j] = m[i];
else if(j < a[i] || dp[j-a[i]] <= 0){
dp[j] = -1;
}
else dp[j] = dp[j-a[i]] - 1;
}
}
if(dp[sum] >= 0) puts("Can be divided.");
else puts("Can't be divided.");
puts("");
}
return 0;
}
五、LIS問題
題目:Longest Ordered Subsequence
int a[maxn];
int dp[maxn];
int main()
{
int n; scanf("%d", &n);
rep(i, 1, n) scanf("%d", a + i);
fill(dp, dp + n + 1, inf);
rep(i, 1, n){
*lower_bound(dp + 1, dp + n + 1, a[i]) = a[i];
}
printf("%d\n", lower_bound(dp + 1, dp + n + 1, inf) - dp - 1);
return 0;
}
六、優先隊列的定義&重載
struct node{
int x, y, t;
friend bool operator < (node a, node b){
return a.t > b.t;
}
};
priority_queue<node> q;
七、並查集
題目:The Suspects
int fa[maxn];
int n, m;
int Find(int x){
return x == fa[x] ? x : fa[x] = Find(fa[x]);
}
void uni(int x, int y){
fa[Find(x)] = Find(y);
}
void init(){
rep(i, 0, n) fa[i] = i;
}
int main()
{
while(~scanf("%d %d", &n, &m) && !(!n && !m)){
init();
rep(i, 1, m){
int num; scanf("%d", &num);
int x; scanf("%d", &x);
rep(j, 1, num - 1){
int y; scanf("%d", &y);
uni(x, y);
}
}
int fa0 = Find(0);
int cnt = 1;
rep(i, 1, n - 1){
if(Find(i) == fa0) cnt++;
}
printf("%d\n", cnt);
}
return 0;
}
八、最短路問題
floyd:
問題:Cow Contest (求有向圖傳遞閉包)
bool vis[maxn][maxn];
int main()
{
int n, m; scanf("%d %d", &n, &m);
rep(i, 1, n) vis[i][i] = 1;
rep(i, 1, m){
int u, v; scanf("%d %d", &u, &v);
vis[u][v] = 1;
}
rep(k, 1, n){
rep(i, 1, n){
rep(j, 1, n){
vis[i][j] |= (vis[i][k] && vis[k][j]);
}
}
}
int cnt = 0;
rep(i, 1, n){
bool f = 1;
rep(j, 1, n){
if(!vis[i][j] && !vis[j][i]) f = 0;
}
if(f) cnt++;
}
printf("%d\n", cnt);
return 0;
}
Bellman_Ford:
題目:Wormholes
struct edge{
int from, to, cost;
}e[maxn];
int d[maxn];
int n, m, m2;
bool Bellman_Frod(int s){
memset(d, 0, sizeof(d));
rep(i, 1, n){
rep(j, 1, 2 * m + m2){
edge t = e[j];
if(d[t.to] > d[t.from] + t.cost){
d[t.to] = d[t.from] + t.cost;
if(i == n) return true;
}
}
}
return false;
}
int main()
{
int t; scanf("%d", &t);
while(t--){
scanf("%d %d %d", &n, &m, &m2);
rep(i, 1, m){
scanf("%d %d %d", &e[i].from, &e[i].to, &e[i].cost);
e[i+m].from = e[i].to, e[i+m].to = e[i].from, e[i+m].cost = e[i].cost;
}
rep(i, 2 * m + 1, 2 * m + m2){
scanf("%d %d %d", &e[i].from, &e[i].to, &e[i].cost);
e[i].cost = -e[i].cost;
}
puts(Bellman_Frod(1) ? "YES" : "NO");
}
return 0;
}