2021/7/12模拟赛

动态规划+图论专题模拟赛

这场比赛过后,应该再也不会有人 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=1MbiK,感觉就是个 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 dijkstralyn大佬的 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 都排不到

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值