动态规划+图论专题模拟赛
这场比赛过后,应该再也不会有人 F a k e Fake Fake 我了,因为我是真的菜
T1
给 N N N 个数 a i a_i ai,需要一个长度为 M M M 的序列 b i b_i bi ,满足 ∑ i = 1 M b i ≤ K \sum\limits^M_{i=1}b_i \le K i=1∑Mbi≤K,感觉就是个 D P DP DP
//T1
#include<bits/stdc++.h>
using namespace std;
bool flag;
int n,m,k;
long long f[205][205],ans,a[3010];
int main()
{freopen("sequence.in","r",stdin);freopen("sequence.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);//memset(f,0,sizeof f);
for(int i=1;i<=n;i++){scanf("%lld",&a[i]);if(a[i]>a[i-1])flag=1;}
if(m==k||flag==0){cout<<(m*a[1]);return 0;}
for(int i=1;i<=m;i++)//取到第d_i
for(int g=1;g<=n;g++)//d_i取g
for(int j=g;j<=k;j++)//总花费代价为j
f[i][j]=max(f[i-1][j-g]+a[g],f[i][j]);
for(int i=1;i<=k;i++)ans=max(ans,f[m][i]);
// for(int g=1;g<=m;g++)
// {
// for(int i=1;i<=k;i++)
// {
// for(int j=1 ;j<=n;j++)
// {
// ans=max(ans,f[g][i]);
// cout<<f[g][i][j]<<' ';
// }
// puts("");
// }
// puts("_____________________________________");
// }
cout<<ans;return 0;
}
O
(
n
3
)
O(n^3)
O(n3)的暴力,加上两个特殊情况,本来应该
50
50
50 的
一开始写了个三维的,然后改了俩小时,并且很认真地打了表,然后发现三维无用,改成二维的就直接过了样例
太离谱了最后出来只剩
15
15
15 分了
后来加上了memset(f,-100,sizeof f);f[0][0]=0;
,初始化后得了
45
45
45 分
其实考试的时候我还以为是需要斜率优化一下
但是吃饭的时候一讨论发现根本不行,正解为:
#include<bits/stdc++.h>
using namespace std;
long long a[30010],n,m,k,f[10100][10010];
int main()
{
scanf("%lld%lld%lld",&n,&m,&k);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
for(int i=1;i<=m;i++)
for(int j=1;j<=k;j++)
for(int g=1;g<=j/i;g++)
f[i][j]=max(f[i][j],f[i-1][j-g]+a[g]);
cout<<f[m][k];
}
T2
大意为:判断一个有向图中,是否至少有两个不含公共边的环
太离谱了,本来想
T
o
p
s
o
r
t
Topsort
Topsort ,发现以我常用的板子很难解这个题,但是实际上
d
f
s
dfs
dfs 是可以拿个部分分的
然而我考场上想的是先找到环,然后把整个环删掉,看还有没有环,然后回复删掉的环,再找个环删掉
…
…
……
…… 直到出现这种情况——删掉了某个环后还能找到环
如果写出来应该能拿些分,但是我太菜了
正解是找到一个环,枚举删掉环上每个边,看是否还有其他环
不过老师的码风是真好看
// 修改自提交记录:247832
// 原记录作者: (UID: 0)
#include <cstdio>
#include <cstring>
#define R register
int F()
{
R int x; R char ch;
while(ch = getchar(), ch < '0' || ch > '9'); x = ch - '0';
while(ch = getchar(), ch >= '0' && ch <= '9') x = ch - '0' + x * 10;
return x;
}
int n, m, Sta[510], tot, Test[510], cnt, Point[510], Next[100010], To[100010], q, missing;
bool vis[510], on_stack[510], flag = 1;
void Add(R int u, R int v){ Next[++q] = Point[u]; Point[u] = q; To[q] = v; }
bool DFS(R int u)
{
vis[u] = on_stack[u] = 1;
for(R int j = Point[u]; j; j = Next[j])
{
if(missing == j) continue;
if(!vis[To[j]])
{
if(flag) Sta[++tot] = j;
if(DFS(To[j])) return 1;
if(flag) tot--;
}
else if(on_stack[To[j]])
{
if(flag)
{
Test[++cnt] = j;
while(tot && To[Sta[tot]] != To[j]) Test[++cnt] = Sta[tot--];
}
return 1;
}
}
on_stack[u] = 0;
return 0;
}
int main()
{
scanf("%d %d", &n, &m);
for(R int i = 1; i <= m; i++)
{
R int u = F(), v = F();
Add(u, v);
}
for(R int i = 1; i <= n; i++) if(!vis[i] && DFS(i)) break;
if(cnt == 0)
{
puts("NO");
return 0;
} flag = 0;
for(R int i = 1; i <= cnt; i++)
{
missing = Test[i];
memset(vis, 0, sizeof(vis));
memset(on_stack, 0, sizeof(on_stack));
for(R int j = 1; j <= n; j++) if(!vis[j] && DFS(j)){ flag = 1; break; }
if(!flag){ puts("NO"); return 0; }
flag = 0;
}
puts("YES");
return 0;
}
T3
不想说啥了,搞了个最小生成树,然后写个 d i j k s t r a dijkstra dijkstra (lyn大佬的 S P F A SPFA SPFA 直接砍下好多分),不知道哪里写错了,一生气改成两个 T o p s o r t Topsort Topsort,终于过了样例,而一开始写完拓扑,每调用,还查了好长时间的错
//T3
#include<bits/stdc++.h>
using namespace std;
struct eo{int x,y,z;}e[300];
bool flag[600];
int hh[600],fa[300],cd[300],rudu[300],l[300],pp,r[300],n,m,a,b,zd[600],tot,nxt[600],hd[300],ans[300],v[600];
bool operator <(eo x,eo y){return x.z<y.z;}
int get(int x)
{
if(fa[x]==x)return x;
return fa[x]=get(fa[x]);
}
void lian(int x,int y,int z){zd[++tot]=y;nxt[tot]=hd[x];hd[x]=tot;v[tot]=z;}
void topsort()
{
queue<int>q;
for(int i=1;i<=n;i++)if(rudu[i]==0)q.push(i);
while(q.size())
{
int x=q.front();q.pop();
for(int i=hd[x];i;i=nxt[i])
{
ans[zd[i]]=min(ans[zd[i]],ans[x]+v[i]);
rudu[zd[i]]--;
if(rudu[zd[i]]<=0)q.push(zd[i]);
}
}
return;
}
//void dijkstra()
//{
// priority_queue<pair<int,int> > q;
// memset(hh,10,sizeof hh);memset(flag,0,sizeof flag);
// q.push(make_pair(0,1));hh[1]=0;
// while(q.size())
// {
// int x=q.top().second;q.pop();
// if(flag[x])continue;
// flag[x]=1;
// for(int i=hd[x];i;i=nxt[i])
// {
// int y=zd[i],z=cd[i];
// if(hh[y]>hh[x]+z){hh[y]=hh[x]+z;q.push(make_pair(-hh[y],y));}
// }
// }
// for(int i=1;i<=n;i++)ans[i]=hh[i];
//}
int main()
{
scanf("%d%d%d%d",&n,&m,&a,&b);memset(ans,10,sizeof ans);ans[1]=0;
for(int i=1;i<=m;i++)scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
sort(e+1,e+m+1);for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=m;i++)
{
int x=get(e[i].x),y=get(e[i].y);
if(x==y)continue;
fa[x]=y;
l[++pp]=min(x,y);r[pp]=max(x,y);cd[pp]=e[i].z;
lian(y,x,e[i].z);rudu[x]++;
// lian(x,y,e[i].z);lian(y,x,e[i].z);
}
topsort();tot=0;
for(int i=1;i<=pp;i++){lian(l[i],r[i],cd[i]);rudu[r[i]]++;hd[i]=0;}
topsort();
// dijkstra();
for(int i=1;i<=n;i++)cout<<ans[i]<<' ';
return 0;
}
T4
圆方图,没写
一共
25
25
25 人,我
15
15
15 分排到第
15
15
15,太离谱了,真菜啊我
不过也确实没啥可说的,我本来作业里的题写的就不多,应该连
15
15
15 都排不到