zoukankan      html  css  js  c++  java
  • NOIP2015题解

    D1T1模拟

    #include<bits/stdc++.h>
    #define re(i,l,r) for(int i=(l);i<=(r);i++)
    using namespace std;
    const int inf=214748364;
    template<typename Q>
    void inin(Q &ret)
    {
    	ret=0;char ch=getchar();
    	while(ch<'0'||ch>'9')ch=getchar();
    	while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
    }
    int n,a[44][44];
    int main()
    {
    	inin(n);
    	int tot=0,x=1,y=n/2+1;
    	while(++tot<=n*n)
    	{
    		a[x][y]=tot;
    		int dx,dy;
    		if(x==1)dx=n;else dx=x-1;
    		if(y==n)dy=1;else dy=y+1;
    		if(a[dx][dy])
    			if(x==n)dx=1;else dx=x+1,dy=y;else ;
    		x=dx,y=dy;
    	}
    	re(i,1,n)re(j,1,n)printf("%d%c",a[i][j],j==n?'
    ':' ');
    	return 0;
    }
    

      D1T2
    由于每个点只有一个出边,所以这张图上每个连通块有且仅有一个环,所以对每个点深搜打标记找最小环即可

    #include<bits/stdc++.h>
    #define re(i,l,r) for(int i=(l);i<=(r);i++)
    using namespace std;
    const int inf=214748364;
    template<typename Q>
    void inin(Q &ret)
    {
    	ret=0;char ch=getchar();
    	while(ch<'0'||ch>'9')ch=getchar();
    	while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
    }
    int n;
    int a[200020],ans=2147483647;
    int bo[200020],dfn[200020];
    void dfs(int x,int sum,int t)
    {
    	bo[x]=t;dfn[x]=sum;
    	if(bo[a[x]]==t){ans=min(ans,sum-dfn[a[x]]+1);return ;}
    	else if(bo[a[x]])return ;
    	dfs(a[x],sum+1,t);
    }
    int main()
    {
    	inin(n);
    	re(i,1,n)inin(a[i]);
    	re(i,1,n)
    		if(!bo[i])dfs(i,1,i);
    	cout<<ans;
    	return 0;
    }
    

      D1T3搜搜搜

    假设不能出顺子是不是很简单?统计单牌、对子和各种搭配,尽量少出几次。

    所以可以单独DFS顺子的情况,对于每种出顺子的方案,再进行上面的方法更新答案

    #include<bits/stdc++.h>
    #define re(i,l,r) for(int i=(l);i<=(r);i++)
    using namespace std;
    const int inf=214748364;
    template<typename Q>
    void inin(Q &ret)
    {
    	ret=0;char ch=getchar();
    	while(ch<'0'||ch>'9')ch=getchar();
    	while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
    }
    int a[16],t,n;
    int ans=2147483647;
    void dfs(int sum)
    {
    	if(sum>=ans)return ;
    	int q=0,w=0,e=0;
    	if(a[15]==1)q++;
    	else if(a[15]==2)e++;
    	re(i,2,14)if(a[i]==1)q++;else if(a[i]==2)w++;
    	re(i,2,14)if(a[i]==4)
    	{
    		e++;
    		if(q>1)q-=2;else if(w>1)w-=2;else if(w>0)w--;
    	}
    	re(i,2,14)if(a[i]==3)
    	{
    		e++;
    		if(q>0)q--;else if(w>0)w--;
    	}
    	ans=min(ans,sum+q+w+e);
        re(i,3,10)
        {
        	int j=i;
            for(;j<=14;j++)
            {
            	a[j]--;
                if(a[j]<0)break;
                if(j>=i+4)dfs(sum+1);
            }
            if(j==15)j--;
            while(j>=i)a[j--]++;
        }
        re(i,3,12)
        {
        	int j=i;
        	for(;j<=14;j++)
        	{
        		a[j]-=2;
        		if(a[j]<0)break;
        		if(j>=i+2)dfs(sum+1);
    		}
    		if(j==15)j--;
    		while(j>=i)a[j--]+=2;
        }
        re(i,3,13)
        {
        	int j=i;
        	for(;j<=14;j++)
        	{
        		a[j]-=3;
        		if(a[j]<0)break;
        		if(j>i)dfs(sum+1);
        	}
        	if(j==15)j--;
        	while(j>=i)a[j--]+=3;
        }
    }
    int main()
    {
    	inin(t),inin(n);
    	while(t--)
    	{
    		memset(a,0,sizeof(a));
    		ans=2147483647;
    		re(i,1,n)
    		{
    			int aa,b;
    			inin(aa),inin(b);
    			if(aa==0)a[15]++;
    			else if(aa==1)a[14]++; 
    			else a[aa]++;
    		}
    		dfs(0);
    		cout<<ans<<"
    ";
    	}
    	return 0;
    }
    

      D2T1二分答案
    二分最小跳跃长度,看能不能在移走不超过m块石头的前提下走到对岸

    #include<bits/stdc++.h>
    #define re(i,l,r) for(int i=(l);i<=(r);i++)
    using namespace std;
    const int inf=214748364;
    template<typename Q>
    void inin(Q &ret)
    {
    	ret=0;char ch=getchar();
    	while(ch<'0'||ch>'9')ch=getchar();
    	while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
    }
    int l,n,m;
    int dis[50050];
    bool check(int M)
    {
    	int now=0,you=m;
    	while(1)
    	{
    		if(now==n)return 1;
    		re(i,now+1,n)if(dis[i]-dis[now]>=M){now=i;break;}
    		else 
    		{
    			you--;
    			if(you<0)return 0;
    		}
    	}
    	return 1;
    }
    int main()
    {
    	inin(l),inin(n),inin(m);
    	re(i,1,n)inin(dis[i]);dis[++n]=l;
    	int L=1,R=l,mid,ans=L;
    	while(L<=R)
    	{
    		mid=(L+R)>>1;
    		if(check(mid))L=mid+1,ans=mid;
    		else R=mid-1;
    	}
    	cout<<ans;
    	return 0;
    }
    

      D2T2   DP

    f[k][i][j]表示用了a的前i个字符,分了k段,匹配了b的前j个字符的方案数

    #include<bits/stdc++.h>
    #define re(i,l,r) for(int i=(l);i<=(r);i++)
    using namespace std;
    const int inf=214748364;
    template<typename Q>
    void inin(Q &ret)
    {
    	ret=0;char ch=getchar();
    	while(ch<'0'||ch>'9')ch=getchar();
    	while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
    }
    const int mod=1000000007;
    int n,m,kk;
    char a[1010],b[220];
    int f[2][1010][220];
    int main()
    {
    	inin(n),inin(m),inin(kk);
    	scanf("%s%s",a+1,b+1);
    	re(i,0,n)f[0][i][0]=1;
    	int d=0;
    	re(now,1,kk)
    	{
    		d^=1;
    		re(i,0,n)f[d][i][now-1]=0;
    		re(i,now,m)for(int j=i;j<=n;j++)
    			if(a[j]==b[i])
    			{
    				f[d][j][i]=((f[d][j-1][i-1]+f[d][j-1][i])%mod+f[d^1][j-1][i-1])%mod;
    				if(j>1)f[d][j][i]=(f[d][j][i]-f[d][j-2][i-1]+mod)%mod;
    			}
    			else f[d][j][i]=f[d][j-1][i];
    	}
    	cout<<f[d][n][m];
    	return 0;
    }
    

      D2T3二分答案+lca

    预处理每个运输计划的lca和长度

    二分答案mid,要修改的边肯定在所有长度大于mid的运输计划中

    所以要求所有长度大于mid的运输计划的边的交集,可以用前缀和解决,最后看交集里有没有删掉它能够使最长的运输计划长度小于mid的边

    #include<bits/stdc++.h>
    #define re(i,l,r) for(int i=(l);i<=(r);i++)
    using namespace std;
    const int inf=214748364;
    template<typename Q>
    void inin(Q &ret)
    {
    	ret=0;char ch=getchar();
    	while(ch<'0'||ch>'9')ch=getchar();
    	while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
    }
    int next[600060],head[300030],zhi[600060],ed,t[600060];
    int top[300030],fa[300030],son[300030],sz[300030],dis[300030],shen[300030];
    int inininin[300030];
    void add(int a,int b,int tt)
    {
    	next[++ed]=head[a],head[a]=ed,zhi[ed]=b,t[ed]=tt;
    	next[++ed]=head[b],head[b]=ed,zhi[ed]=a,t[ed]=tt;
    }
    void dfs(int x)
    {
    	int Max=0;sz[x]=1;
    	for(int i=head[x];i;i=next[i])if(zhi[i]!=fa[x])
    	{
    		fa[zhi[i]]=x;
    		dis[zhi[i]]=dis[x]+t[i];
    		shen[zhi[i]]=shen[x]+1;
    		inininin[zhi[i]]=t[i];
    		dfs(zhi[i]);
    		sz[x]+=sz[zhi[i]];
    		if(sz[zhi[i]]>Max)Max=sz[zhi[i]],son[x]=zhi[i];
    	}
    }
    void dfs(int x,int t)
    {
    	if(!x)return ;
    	top[x]=t;
    	dfs(son[x],t);
    	for(int i=head[x];i;i=next[i])if(zhi[i]!=fa[x]&&zhi[i]!=son[x])
    		dfs(zhi[i],zhi[i]);
    }
    int lca(int x,int y)
    {
    	if(shen[y]>shen[x])swap(x,y);
    	while(top[x]!=top[y])
    		if(shen[top[x]]<shen[top[y]])y=fa[top[y]];
    		else x=fa[top[x]];
    	return shen[x]<shen[y]?x:y;
    }
    struct project
    {
    	int u,v,lca,len;
    }pp[300030];
    int n,m,mmm=2147483647,mmmm,bo[300030];
    void ddfs(int x)
    {
    	for(int i=head[x];i;i=next[i])if(zhi[i]!=fa[x])
    	{
    		ddfs(zhi[i]);
    		bo[x]+=bo[zhi[i]];
    	}
    }
    bool check(int mid)
    {
    	memset(bo,0,sizeof(bo));
    	int cmp=0,sum=0;
    	re(i,1,m)if(pp[i].len>mid)
    	{
    		cmp=max(cmp,pp[i].len-mid);
    		sum++;
    		bo[pp[i].u]++,bo[pp[i].v]++;
    		bo[pp[i].lca]-=2;
    	}
    	ddfs(1);
    	re(i,1,n)if(bo[i]==sum&&inininin[i]>=cmp)return 1;
    	return 0;
    }
    int main()
    {
    	inin(n),inin(m);
    	re(i,2,n)
    	{
    		int q,w,e;
    		inin(q),inin(w),inin(e);
    		add(q,w,e);
    	}
    	re(i,1,m)inin(pp[i].u),inin(pp[i].v);
    	dfs(1);
    	dfs(1,1);
    	re(i,1,m)
    		pp[i].lca=lca(pp[i].u,pp[i].v),
    		pp[i].len=dis[pp[i].u]+dis[pp[i].v]-(dis[pp[i].lca]<<1),
    		mmm=min(mmm,pp[i].len),mmmm=max(mmmm,pp[i].len);
    	int l=0,r=mmmm,mid,ans;
    	while(l<=r)
    	{
    		mid=(l+r)>>1;
    		if(check(mid))r=mid-1,ans=mid;
    		else l=mid+1;
    	}
    	cout<<ans;
    	return 0;
    }
    

      

  • 相关阅读:
    数据类型比较(==)
    uniapp(一)
    小程序分包
    小程序网易云(五)
    java.lang的详解
    有哪些日常节省时间的诀窍?
    怎么把知乎的回答转化成自己的知识?
    linux下搭建hadoop环境
    linux下,免密码登录
    mac下创建用户及赋予sudo权限
  • 原文地址:https://www.cnblogs.com/HugeGun/p/5693803.html
Copyright © 2011-2022 走看看