T1
回家路线==归程?
题面又臭又长。。
先瞅几眼数据范围,A=B=C的部分分是什么玩意?
最早到达时间?
A=B=0似乎可以Dp?
后来想到一种时间复杂度玄学的DP
d
p
[
u
]
[
t
]
表
示
在
时
间
t
到
达
u
的
最
小
代
价
dp[u][t]表示在时间t到达u的最小代价
dp[u][t]表示在时间t到达u的最小代价
转移方程:
d
p
[
u
]
[
t
]
=
d
p
[
v
]
[
q
[
i
]
]
+
F
(
p
[
i
]
−
t
)
dp[u][t]=dp[v][q[i]]+F(p[i]-t)
dp[u][t]=dp[v][q[i]]+F(p[i]−t)
边界:
d
p
[
u
]
[
t
]
=
t
dp[u][t]=t
dp[u][t]=t
70%范围内跑的飞快
Code:
#include <bits/stdc++.h>
#define maxn 2010
#define maxt 1010
#define maxm 200010
#define LL long long
using namespace std;
const LL inf = 1e12;
struct Edge{
int to, next, p, q;
}edge[maxm];
int num, head[maxn], n, m, A, B, C;
LL dp[maxn][maxt];
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
void addedge(int x, int y, int p, int q){ edge[++num] = (Edge) { y, head[x], p, q }; head[x] = num; }
LL F(int x){ return 1LL * A * x * x + B * x + C; }
void dfs(int u, int t){
if (u == n) dp[u][t] = t;
if (dp[u][t] < inf) return;
for (int i = head[u]; i; i = edge[i].next){
int v = edge[i].to;
if (edge[i].p >= t){
dfs(v, edge[i].q);
dp[u][t] = min(dp[u][t], dp[v][edge[i].q] + F(edge[i].p - t));
}
}
}
int main(){
freopen("route.in", "r", stdin);
freopen("route.out", "w", stdout);
n = read(), m = read(), A = read(), B = read(), C = read();
for (int i = 1; i <= m; ++i){
int x = read(), y = read(), p = read(), q = read();
addedge(x, y, p, q);
dp[y][q] = inf;
}
dp[1][0] = inf;
/* for (int i = 1; i <= n; ++i)
for (int j = 0; j <= 1000; ++j) dp[i][j] = inf;*/
dfs(1, 0);
printf("%lld\n", dp[1][0]);
return 0;
}
T2
20%暴力随便打好
希望找一下规律失败
这题没怎么思考,就这样了
Code:
#include <bits/stdc++.h>
#define maxn 310
#define qy 1000000007
using namespace std;
int a[maxn], b[maxn], ans, n, num[maxn];
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
void Do(){
for (int s = 1; s <= n; ++s){
int x = 0, i = s - 1;
while (i >= 1 && num[i] <= num[s]) ++x, --i;
int y = 0, j = s + 1;
while (j <= n && num[j] < num[s]) ++y, ++j;
if (abs(x - y) > 2) return;
}
(++ans) %= qy;
}
void dfs(int k){
if (k > n) Do(); else{
for (int i = a[k]; i <= b[k]; ++i){
num[k] = i;
dfs(k + 1);
}
}
}
int main(){
freopen("robot.in", "r", stdin);
freopen("robot.out", "w", stdout);
n = read();
for (int i = 1; i <= n; ++i) a[i] = read(), b[i] = read();
dfs(1);
printf("%d\n", ans);
return 0;
}
T3
马上设计出了28分
O
(
n
4
)
的
水
d
p
O(n^4)的水dp
O(n4)的水dp
d
p
[
i
]
[
s
l
]
[
k
1
]
[
k
2
]
表
示
第
i
位
,
总
共
s
l
位
下
标
相
同
,
各
取
了
k
1
,
k
2
个
dp[i][sl][k1][k2]表示第i位,总共sl位下标相同,各取了k1,k2个
dp[i][sl][k1][k2]表示第i位,总共sl位下标相同,各取了k1,k2个
转移方程:
d
p
[
i
]
[
s
l
]
[
k
1
]
[
k
2
]
=
m
a
x
(
d
p
[
i
−
1
]
[
s
l
−
1
]
[
k
1
−
1
]
[
k
2
−
1
]
+
a
[
i
]
+
b
[
i
]
,
d
p
[
i
−
1
]
[
s
l
]
[
k
1
−
1
]
[
k
2
]
+
a
[
i
]
,
d
p
[
i
−
1
]
[
s
l
]
[
k
1
]
[
k
2
−
1
]
+
b
[
i
]
,
d
p
[
i
−
1
]
[
s
l
]
[
k
1
]
[
k
2
]
)
dp[i][sl][k1][k2]=max(dp[i-1][sl-1][k1-1][k2-1]+a[i]+b[i],dp[i-1][sl][k1-1][k2]+a[i],dp[i-1][sl][k1][k2-1]+b[i],dp[i-1][sl][k1][k2])
dp[i][sl][k1][k2]=max(dp[i−1][sl−1][k1−1][k2−1]+a[i]+b[i],dp[i−1][sl][k1−1][k2]+a[i],dp[i−1][sl][k1][k2−1]+b[i],dp[i−1][sl][k1][k2])
A
N
S
=
m
a
x
(
d
p
[
n
]
[
i
]
[
k
]
[
k
]
)
(
l
<
=
i
<
=
k
)
ANS=max(dp[n][i][k][k])(l<=i<=k)
ANS=max(dp[n][i][k][k])(l<=i<=k)
Code:
#include <bits/stdc++.h>
#define LL long long
#define maxn 32
using namespace std;
int n, K, L;
LL dp[2][maxn][maxn][maxn], a[maxn], b[maxn];
inline LL read(){
LL s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
int main(){
freopen("sequence.in", "r", stdin);
freopen("sequence.out", "w", stdout);
int M = read();
while (M--){
n = read(), K = read(), L = read();
for (int i = 1; i <= n; ++i) a[i] = read();
for (int i = 1; i <= n; ++i) b[i] = read();
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; ++i){
int p = i & 1;
for (int j = 0; j <= K; ++j)
for (int k = j; k <= K; ++k)
for (int l = j; l <= K; ++l){
dp[p][j][k][l] = dp[p ^ 1][j][k][l];
if (j && k && l) dp[p][j][k][l] = max(dp[p][j][k][l], dp[p ^ 1][j - 1][k - 1][l - 1] + a[i] + b[i]);
if (k) dp[p][j][k][l] = max(dp[p][j][k][l], dp[p ^ 1][j][k - 1][l] + a[i]);
if (l) dp[p][j][k][l] = max(dp[p][j][k][l], dp[p ^ 1][j][k][l - 1] + b[i]);
}
}
int p = n & 1;
LL ans = 0;
for (int i = L; i <= K; ++i) ans = max(ans, dp[p][i][K][K]);
printf("%lld\n", ans);
}
return 0;
}
也不知道什么时候公布成绩。。。
期望得分70+20+28=118
本文针对三道算法竞赛题目提供了详细的解答思路与代码实现,包括一个时间复杂度玄学的DP问题、一个暴力求解的问题以及一个O(n^4)的水DP问题。
453

被折叠的 条评论
为什么被折叠?



