模拟测试(vj2)

比较菜啊本人,只写出来了1~2题,但是后来订正完了的精神也是值得鼓励的~

不多说,总结一下吧

T1.根据题意进行模拟,每个奇数行用'#'涂满,然后判断是否是4的倍数涂旁边的'#'答案就可以出来了~

#include<bits/stdc++.h>
using namespace std;
int n,m;
int b[1000][1000];
int main()
{
	cin>>n>>m;
	int x=0,y=0;
	int sx=0,sy=1;
	int judge=0;
	for(int i=1;i<=n;i+=2)
		for(int j=1;j<=m;j++)
			b[i][j]=1;
	for(int i=2;i<=n;i+=2){
		if(i%4==2) b[i][m]=1;
		else b[i][1]=1;}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++)
			cout<<((b[i][j]==1)?'#':'.');
			cout<<"\n";}
	return 0;
} 

  T2.一遍dfs或者bfs判断这个点是否有没有走过,我们记录他的父节点,然后就可以出来了。

优化,一个字母出现的次数>=4才搜索

#include<bits/stdc++.h>
using namespace std;
int n,m;
int b[100][100];
int book[100][100];
int du[300],vis[200];
int temp[4][2]={{1,0},{-1,0},{0,-1},{0,1}};
int ok=0;

void dfs(int x,int y,int fx,int fy,int color)
{
	if(ok) return ;
	for(int k=0;k<4;k++)
	{
		int u=x+temp[k][0];
		int v=y+temp[k][1];
		if(u<=0||v<=0||u>n||v>m||(u==fx&&v==fy)) continue;
		if(b[u][v]==color)
		{
			if(book[u][v]==color) {ok=1;return ;}
			book[u][v]=color;
			dfs(u,v,x,y,color);
		}
	}
}

int main()
{
	cin>>n>>m;
	char c;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			c=getchar();
			while(c=='\n'||c=='\r')
				c=getchar();
			b[i][j]=c;
			du[c]++;
		}
	for(int k=0;k<=200;k++)
		if(du[k]>=4)
		{
			ok=0;	
			memset(book,0,sizeof(book));
			for(int i=1;i<=n;i++)
				for(int j=1;j<=m;j++)
					if(b[i][j]==k&&book[i][j]==0)	
					{
						book[i][j]=k;
						dfs(i,j,-1,-1,k);
						if(ok) {cout<<"Yes\n";return 0;}
					}
		}
	cout<<"No\n";
	return 0;
} 

 

  T3.拓扑排序,因为前面的字母的都比后面的要大,于是就可以想到topusort,给每一个节点连一条有向边,然后计算入度就可以了。

注意:abc ab这样的字母要进行特判,因为这种情况是不存在的。

这题打到一半,快出结果了,没时间上交了。虽然思路也是yy来的(逃)

#include<bits/stdc++.h>
using namespace std;
int n;
char s[200],pre[200];
int in[200];
int ans[200];
vector<int> G[123];
int flag=0;
int topusort()
{
	queue<int> q;
	for(int i=0;i<26;i++)
		if(!in[i]) q.push(i);
	int top=0;
	while(!q.empty())
	{
		int x=q.front();q.pop();
		ans[++top]=x;
		for(int i=0;i<G[x].size();i++)
		{
			int m=G[x][i];
			if(in[m]==1) q.push(m);
			if(in[m]) in[m]--;
		}
	}
	if(top!=26||flag)
		cout<<"Impossible\n";
	else
	{
		for(int i=1;i<=top;i++)
			cout<<char(ans[i]+'a');
	}
	
}

int main()
{
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>s;
		int ok=0;
		for(int j=0;j<min(strlen(s),strlen(pre));j++)
		{
			if(s[j]!=pre[j])
			{
			 G[pre[j]-'a'].push_back(s[j]-'a');
			 in[s[j]-'a']++;
				ok=1;
				break;
			}	
		}
		if(!ok&&strlen(pre)>strlen(s))
			{flag=1;break;}
		strcpy(pre,s);
	}
	topusort();
	/*for(int i=0;i<122;i++)
		if(G[i].size())
			cout<<G[i][0]<<endl;*/
	return 0;
} 

  T4.exgcd,当ax+by=1有解得情况是,x,y互质,于是就可以转换成一个背包问题,具体看代码批注。

//找出为1的最大公约数,把他看成背包问题,看每个数对因子的贡献
//每个数都有选或者不选,
#include<bits/stdc++.h>
using namespace std;
int n;
int l[300000],c[300000];
map<int,int> dp;
int gcd(int a,int b)//gcd(a,b)=gcd(b,a);
{
	return b==0?a:gcd(b,a%b);
}

int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>l[i];
	for(int i=1;i<=n;i++)
		cin>>c[i];
	dp.clear();
	dp[0]=0;//map初始化为0 
	map<int,int> ::iterator it;//为std::pair的类型dp[a]=b,first=a,second=b; 
	for(int i=1;i<=n;i++)
	{
		for(it=dp.begin();it!=dp.end();it++)//左闭右开stl 
		{
			int t=it->first;
			int tt=gcd(l[i],t);
			if(dp.count(tt))//返回该元素出现的个数 
				dp[tt]=min(dp[tt],it->second+c[i]);
			else dp[tt]=it->second+c[i];
		}
	}
	if(!dp.count(1)) cout<<"-1\n";
	else cout<<dp[1]<<endl;
	return 0;
} 

  T5.网络流问题。(前排的大神用二分图匹配做出来了,待会儿听听讲解吧orz~)我的想法也是参考网上的大神的

首先我们可以知道相邻两个是素数的话一定是异奇偶,因为素数为2的情况已经被排除。于是我们就可以建立一个虚拟巨大节点,以及虚拟巨大汇点,然后建立一条从源点到偶数节点容量为2的边,因为一个数旁边有两个奇数,同理再建立奇数节点到汇点容量为2的边。我们再分别枚举所有的节点,找出和为素数的节点,并连上一条为1的边,然后跑一边最大流(我不会写最大流,于是就拷贝了之前写的,发现竟然有错误恼)。

如果流==n那就存在,一遍dfs跑出满容量的边,然后输出就可以了。

#include<bits/stdc++.h>
#define maxn 2140000
using namespace std;

struct{int to,next,w;}e[maxn];
int head[maxn],ly[maxn],lx[maxn],a[maxn],prime[maxn],cur[maxn],gap[maxn],h[maxn],vis[maxn];
vector<int> mp[12004];
int cnt=0,n,ss,tt;

void add(int u,int v,int w){
	e[cnt].to=v;e[cnt].w=w;e[cnt].next=head[u];head[u]=cnt++;
}

void init()
{
	prime[1]=1;
	for(int i=2;i<=sqrt(165540);i++)
		if(!prime[i])
			for(int j=i*i;j<=165540;j+=i)
				prime[j]=1;
}

void get()
{
	ss=n+1;tt=ss+1;
	int cntx=0,cnty=0;
	memset(head,-1,sizeof(head));
	for(int i=1;i<=n;i++)
	{
		if(a[i]%2==0)
		{
			add(ss,i,2);add(i,ss,0);
			lx[cntx++]=i;
		}
		else
		{
			add(i,tt,2);add(tt,i,0);
			ly[cnty++]=i;
		}
	}
	for(int i=0;i<cntx;i++) 
		for(int j=0;j<cnty;j++)
			if(prime[a[lx[i]]+a[ly[j]]]==0)
				add(lx[i],ly[j],1),add(ly[j],lx[i],0);
}

int isap(int x,int fr)
{
    if(x==tt)
       return fr;
    int rest=0;
    for(int i=cur[x];~i;i=e[i].next)
    {
        int j=e[i].to;
        if(h[j]+1==h[x]&&e[i].w)
         {
            int f=isap(j,min(e[i].w,fr-rest));
            e[i].w-=f;
            e[i^1].w+=f;
            rest+=f;
            if(rest==fr)  return fr;
            if(e[i].w) cur[x]=i;
         }
    }
    --gap[h[x]];
    if(!gap[h[x]]) h[ss]=n+4;
    h[x]++;gap[h[x]]++;
    cur[x]=head[x];
    return rest;
}

int maxflow()
{
	int ans=0;
	for(int i=1;i<=n+2;i++) cur[i]=head[i];
	while(h[ss]<n+4)
      ans+=isap(ss,1e9);
    return ans;
}

int dfs(int x,int num)
{
	mp[num].push_back(x);
	vis[x]=1;
	for(int i=head[x];~i;i=e[i].next)
	{
		int j=e[i].to;
		if(vis[j]) continue;
		if(j!=ss&&j!=tt)
			if((i%2==0&&e[i].w==0)||(i%2==1&&e[i^1].w==0))
				dfs(j,num);
	}
}

void output(int num)
{
	for(int i=1;i<=num;i++)
	{
		cout<<mp[i].size();
		for(int j=0;j<mp[i].size();j++)
			cout<<" "<<mp[i][j];
		cout<<"\n";
	}
}

int main()
{
	init();
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	get();
	int tmp=maxflow();
	//cout<<tmp<<endl;	
	if(tmp==n)
	{
		int num=0;
		memset(vis,0,sizeof(vis));
		for(int i=1;i<=n;i++) if(!vis[i]) dfs(i,++num);
		cout<<num<<endl;
		output(num);
	}
	else cout<<"Impossible\n";
	return 0;
} 

  今天的状态还算比较不错吧,毕竟我是一只蒟蒻,up++;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值