[考试总结]20210524

我好菜啊

这次考试真的是很有必要,也是找到了很多的弱点,也发现自己真的是很,还有很多要提升的地方,很多的知识点还需要巩固,做题之前也一定要把给出的样例搞懂再想着去打,不然打的越多,越浪费时间。

对于这一次考试,发现自己的心态还是出现了一些问题,在发现自己的T1的样例怎么也是过不去的时候,心态就已经出现了很大的问题,在转头放弃T1的时候自己心中还是一直在想着T1,以至于在打T2T3的时候也没有打对,所以说心态还是很重要的。

T1:

对于他们在一个点的转移,他们会选择自己可以到达的并且可以玩完的地点进行转移!!!

这就是我sb的地方

对于状态的转移与初末状态也是非常好找,我们不妨设 \(f_{i,j}\) 为这个小朋友在 \(i\) 位置,花费了 \(j\) 时间所能获得的最大开心度期望值,所以最终我们想要的状态就是 \(f_{n,k}\),完全可以考虑搜索,就从 \(f_{n,k}\) 进入搜索,之后在边界进行赋值,只有算出 \(f_{n,k}\) 的值就是最终的答案。

搜索 \(code :\)



#include<cmath>
#include<queue>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define m(c,num) memset(c,num,sizeof c)
#define INF 0x7f7f7f7f
#define debug cout<<"debug"<<endl
namespace xin_io
{
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
	char buf[1<<20],*p1 = buf,*p2 = buf;
	FILE* a14;
	inline void openfile() {a14 = freopen("data.txt","r",stdin);}
	inline void outfile()  {a14 = freopen("o.txt","w",stdout);}
	inline int get()
	{
		int s = 0,f = 1;
		register char ch = gc();
		while(!isdigit(ch))
		{
			if(ch == '-') f = -1;
			ch = gc();
		}
		while(isdigit(ch))
		{
			s = s * 10 + ch - '0';
			ch = gc();
		}
		return  s * f;
	}
}
using namespace xin_io;
static const int maxn = 1e2 + 10;
static const int maxm = 1e6 + 10;
namespace xin
{
	int n,m,k;
	int c[maxn],h1[maxn],h2[maxn];
	class xin_edge
	{
		public:
			int next,w,ver;
	}edge[maxm];
	int head[maxm],zhi = 0;
	inline void add(int x,int y,int z)
	{
		edge[++zhi].ver = y; edge[zhi].w = z;
		edge[zhi].next = head[x]; head[x] = zhi;
	}
	double f[maxn][maxn * 6];
	double ans1 = 0.0,ans2 = 0.0;
	bool pan = 0;
	double dfs(int tim,int x)
	{
//		cout<<"time = "<<tim<<" loc = "<<x<<" f[x][tim] = "<<f[x][tim]<<endl;
		if(f[x][tim]) return f[x][tim];
		int cnt = 0;
		for(register int i=head[x];i;i=edge[i].next)
			if(tim - c[edge[i].ver] - edge[i].w >= 0)
				cnt++;
		if(!pan) f[x][tim] += h1[x];
		else f[x][tim] += h2[x];
		if(!cnt) return f[x][tim];
		for(register int i=head[x];i;i=edge[i].next)
		{
			register int y = edge[i].ver,z = edge[i].w;
			if(tim - z - c[y] >= 0)
				f[x][tim] += dfs(tim - z - c[y],y) / ( 1.0 * cnt);
		}
		return f[x][tim];
	}
	inline short main()
	{
	#ifndef ONLINE_JUDGE
		openfile();
	#endif
		n = get(); m = get(); k = get();
		for(register int i=1;i<=n;++i) c[i] = get(),h1[i] = get(),h2[i] = get();
		for(register int i=1;i<=m;++i) 
		{
			register int x = get(),y = get(),z = get();
			add(x,y,z); add(y,x,z);
		}
		for(register int i=1;i<=n;++i)
			ans1 += dfs(k - c[i],i);//,ans2 += sdf(c[i],i);
		memset(f,0.0,sizeof f);
		pan = 1;
		for(register int i=1;i<=n;++i)
			ans2 += dfs(k - c[i],i);
//		for(register int i=1;i<=n;++i)
//			for(register int j=1;j<=k;++j)
//				cout<<"i = "<<i<<" j = "<<j<<" f[i][j] = "<<f[i][j]<<endl;
		printf("%.5lf %0.5lf\n",ans1 / n,ans2 / n);
		return 0;
	}
}
signed main() {return xin::main();}

当然一般的线性递推也是可以的

线性递推 \(code:\)



#include<cmath>
#include<queue>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define m(c,num) memset(c,num,sizeof c)
#define INF 0x7f7f7f7f
#define debug cout<<"debug"<<endl
namespace xin_io
{
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
	char buf[1<<20],*p1 = buf,*p2 = buf;
	inline void openfile() {freopen("t.txt","r",stdin);}
	inline void outfile()  {freopen("o.txt","w",stdout);}
	inline int get()
	{
		int s = 0,f = 1;
		register char ch = gc();
		while(!isdigit(ch))
		{
			if(ch == '-') f = -1;
			ch = gc();
		}
		while(isdigit(ch))
		{
			s = s * 10 + ch - '0';
			ch = gc();
		}
		return  s * f;
	}
}
using namespace xin_io;
static const int maxn = 1e6 + 10;
namespace xin
{
	int n,m,k;
	int h1[maxn],h2[maxn],c[maxn];
	class xin_edge
	{
		public:	
			int ver,next;
			int w;
	}edge[maxn<<1];
	int head[maxn],zhi = 0;
	inline void add(int x,int y,int z)
	{
		edge[++zhi].ver = y; edge[zhi].w = z;
		edge[zhi].next = head[x]; head[x] = zhi;
	}
	double ans1 = 0.0;
	double ans2 = 0.0;
	void dfs(int ms,int x,int fa,double p,int now)
	{
		int cnt = 0;
		for(register int i=head[x];i;i=edge[i].next)
		{
			register int y = edge[i].ver,z = edge[i].w;
			if(now + z + c[y] <= ms)
				cnt++;
		}
		double pnow = p;
		ans1 += pnow * h1[x];
		ans2 += pnow * h2[x];
		if(cnt) pnow = p / (1.0 * cnt);
//		cout<<"x = "<<x<<"  time = "<<now<<"  more = "<<pnow * h1[x]<<" p = "<<pnow<<endl;
		for(register int i=head[x];i;i=edge[i].next)
		{
			register int y = edge[i].ver,z = edge[i].w;
			if(now + z + c[y] <= k) dfs(ms,y,x,pnow,now + z + c[y]);
		}
	}
	double f[101][481],g[101][481];
	inline short main()
	{
	#ifndef ONLINE_JUDGE
		openfile();
	#endif
		n = get(); m = get(); k = get();
		for(register int i=1;i<=n;++i)
			c[i] = get(),h1[i] = get(),h2[i] = get();
		for(register int i=1;i<=m;++i)
		{
			register int x = get(),y = get(),z = get();
			add(x,y,z); add(y,x,z);
		}
		for(register int j=k;j;--j)
		{
			for(register int i=1;i<=n;++i)
			{
				f[i][j] = h1[i]; g[i][j] = h2[i];
				int cnt = 0;
				for(register int x=head[i];x;x=edge[x].next)
					if(edge[x].w + j + c[edge[x].ver] <= k)
						cnt++;
				for(register int x=head[i];x;x=edge[x].next)
				if(edge[x].w + c[edge[x].ver] + j <= k)
				{
					f[i][j] += f[edge[x].ver][j + edge[x].w + c[edge[x].ver]] / (1.0 * cnt);
					g[i][j] += g[edge[x].ver][j + edge[x].w + c[edge[x].ver]] / (1.0 * cnt);
				}
			}
		}
		for(register int i=1;i<=n;++i)
		{
			ans1 += f[i][c[i]] / (1.0 * n);
			ans2 += g[i][c[i]] / (1.0 * n);
		}
		printf("%.5lf %.5lf\n",ans1,ans2);
		return 0;
	}
}
signed main() {return xin::main();}

T2:

这题目一看就是高斯消元,(还不是自己之前做过开关问题。。。)

\(x_i\) 表示第 \(i\) 个点是否打开,1为开,0为关,所以方程就很好列出。

但是,这里就存在一个很致命的问题:

方程的解似乎是不唯一的

所以到最后就会出现不定方程,之后暴搜每一个自由元的取值反正范围小,随便搜呗

所以 \(code:\)



#include<cmath>
#include<queue>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define m(c,num) memset(c,num,sizeof c)
#define INF 0x7f7f7f7f
#define debug cout<<"debug"<<endl
namespace xin_io
{
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
	char buf[1<<20],*p1 = buf,*p2 = buf;
	inline void openfile() {freopen("data.txt","r",stdin);}
	inline void outfile()  {freopen("o.txt","w",stdout);}
	inline int get()
	{
		int s = 0,f = 1;
		register char ch = gc();
		while(!isdigit(ch))
		{
			if(ch == '-') f = -1;
			ch = gc();
		}
		while(isdigit(ch))
		{
			s = s * 10 + ch - '0';
			ch = gc();
		}
		return  s * f;
	}
}
using namespace xin_io;
#define moy(c) cout<<sizeof(c) / ( 1<< 20)<<" MB"<<endl;
static const int maxn = 1e2+10;
namespace xin
{
	int n;
	int a[maxn][maxn];
	vector < int > link[maxn];
	int b[maxn];
	int ans = 0x7f7f7f7f;
	inline void gs()
	{
		for(register int i=1;i<=n;++i)
		{
			int r = i;
			for(register int j=i;j<=n;++j)
				if(a[j][i]) {r = j; break;}
//			if(!a[r][i]) continue;
			if(r != i)
				for(register int j=i;j<=n+1;++j)
					swap(a[i][j],a[r][j]);
			for(register int j=i+1;j<=n;++j)
				if(a[j][i])
					for(register int k=n+1;k>=i;--k)
						a[j][k] ^= a[i][k];
		}
	}
	void dfs(int x,int now)
	{
		if(now >= ans)return;
		if(x == 0) {ans = now;return;}
		if(a[x][x])
		{
			b[x] = a[x][n+1];
			for(register int j=x+1;j<=n;++j)
				b[x] ^= b[j] * a[x][j];
			dfs(x-1,now+b[x]);
		}
		else
		{
			b[x] = 0; dfs(x-1,now);	b[x] = 1; dfs(x-1,now+1);
		}
	}
	inline short main()
	{
	#ifndef ONLINE_JUDGE
		openfile();
	#endif	
		while(1)
		{
			n = get();
			if(!n) return 0;
			for(register int i=1;i<=n-1;++i)
			{
				register int x = get(),y = get();
				link[x].push_back(y);
				link[y].push_back(x);
			}
			for(register int i=1;i<=n;++i)
			{
				a[i][i] = 1; a[i][n+1] = 1;
				for(register int j=0;j<link[i].size();++j)
					a[i][link[i][j]] = 1;
			}
//			for(register int i=1;i<=n;++i,putchar('\n'))
//				for(register int j=1;j<=n+1;++j)
//					cout<<a[i][j]<<' ' ;cout<<endl;
			gs();
			ans = 0x7f7f7f7f;
//			for(register int i=1;i<=n;++i,putchar('\n'))
//				for(register int j=1;j<=n+1;++j)
//					cout<<a[i][j]<<' ';
			dfs(n,0);
			printf("%d\n",ans);
			memset(a,0,sizeof a); memset(b,0,sizeof b);
			for(register int i=1;i<=n;++i) link[i].clear();
		}
		return 0;
	}
}
signed main() {return xin::main();}

T3:

这个题就比较魔性了,状压是我没有想到的

f[i][j][k][l]表示前i位,用了j次道路,i的前K位(包括i)状态的奇偶性,此时考虑i和i-K+l的连边

如果这条边连,f[i][j+1][k^(1<<K)^(1<<l)]+=f[i][j][k][l];

如果不连,f[i][j][k][l+1]+=f[i][j][k][l],

如果l==K,f[i+1][j][k>>1][0]+=f[i][j][k][l];

特殊判断i-K+l<=0的状态不合法

这个说实话以现在的水平,完全想不到,所以还需要加强

code就不贴出来了,方程明白了自然code就出来了。

总之,这次考试真的带给我了许多,暴露了很多很多问题,自己也是菜得连个暴搜都没有打对。认清自己的问题,善莫大焉。

posted @ 2021-05-30 17:03  NP2Z  阅读(43)  评论(0编辑  收藏  举报