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

    NOIP2010题解

    显然原来都写过,都重新写一遍。

    机器翻译 translate

    一道很容易的模拟题,直接使用一个队列维护一下顺序就好了。

    #include<iostream>
    #include<cstdio>
    #include<queue>
    using namespace std;
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    bool vis[1050];
    int Q[1050],h,t,ans,n,m;
    int main()
    {
    	m=read();n=read();h=1;t=0;
    	for(int i=1;i<=n;++i)
    	{
    		int x=read();if(vis[x])continue;
    		Q[++t]=x;++ans;vis[x]=true;
    		if(t-h+1>m)vis[Q[h++]]=false;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    

    乌龟棋 tortoise

    一个不难想的(dp)是设(f[i][a1][a2][a3][a4])表示当前在(i)位置,四种卡牌分别用的张数为(a1,a2,a3,a4)时的最大收益。不难发现(i)可以通过后面四个数算出来,显然是一个多余状态,去掉后直接(dp)即可。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define MAX 400
    void cmax(int &x,int y){if(x<y)x=y;}
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    int n,m;
    int a[MAX],b[5];
    int f[45][45][45][45];
    int main()
    {
    	n=read();m=read();
    	for(int i=1;i<=n;++i)a[i]=read();
    	for(int i=1;i<=m;++i)b[read()]+=1;
    	memset(f,-63,sizeof(f));
    	f[0][0][0][0]=a[1];
    	for(int i=0;i<=b[1];++i)
    		for(int j=0;j<=b[2];++j)
    			for(int k=0;k<=b[3];++k)
    				for(int l=0;l<=b[4];++l)
    				{
    					int s=1*i+2*j+3*k+4*l+1;
    					if(i)cmax(f[i][j][k][l],f[i-1][j][k][l]+a[s]);
    					if(j)cmax(f[i][j][k][l],f[i][j-1][k][l]+a[s]);
    					if(k)cmax(f[i][j][k][l],f[i][j][k-1][l]+a[s]);
    					if(l)cmax(f[i][j][k][l],f[i][j][k][l-1]+a[s]);
    				}
    	printf("%d
    ",f[b[1]][b[2]][b[3]][b[4]]);
    	return 0;
    }
    

    关押罪犯 prison

    很妙的题目,如果没有做过类似题目的话自己基本不可能做出来。

    不难想到的一点是这样的,我们把所有限制按照权值从大往小排序,因为要最大值最小,所以显然竟可能的满足权值较大的限制。但是我们发现限制是(x,y)不能在一个集合。那么对于每一个点拆成两个,一个表示和它在一个集合,一个表示和它不在一个集合。对于一个限制,如果(x,y)已经在一个集合内,显然这个限制的权值就是答案了。否则合并(x)(y)的集合关系,即把(x)合并到和(y)不在一个集合内的集合中去,(y)同理。并查集实现即可。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define MAX 40040
    #define MAXL 100100
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    int n,m;
    struct Line{int u,v,w;}e[MAXL];
    bool operator<(Line a,Line b){return a.w>b.w;}
    int f[MAX];
    int getf(int x){return x==f[x]?x:f[x]=getf(f[x]);}
    int main()
    {
    	n=read();m=read();
    	for(int i=1;i<=m;++i)e[i].u=read(),e[i].v=read(),e[i].w=read();
    	sort(&e[1],&e[m+1]);
    	for(int i=1;i<=n+n;++i)f[i]=i;
    	for(int i=1;i<=m;++i)
    	{
    		int u=e[i].u,v=e[i].v;
    		if(getf(u)==getf(v))
    		{
    			printf("%d
    ",e[i].w);
    			return 0;
    		}
    		f[getf(u)]=getf(v+n);
    		f[getf(v)]=getf(u+n);
    	}
    	printf("0
    ");
    	return 0;
    }
    

    引水入城 flow

    也是一道很不错的题目。

    对于判定性问题,不用多想,在每一个位置都建立蓄水场,(bfs)一遍判定是否能够满足所有位置。如果不行就直接输出。否则考虑如何计算最小值。

    继续观察,发现当可以满足所有位置的时候,在每个位置建立蓄水场,那么它影响的范围一定是一段连续区间。证明不难。如果不是一段区间的话,假设(x)为其中的一个分割位置,因为有解,所以(x)必定能被(x-1,x+1)(x)上一行这三个格子中的一个影响到,而(x)割开了一个线段,那么必定跨越(x)这一列,所以不可能不影响到(x)位置。所以必定是一段连续区间。

    那么问题转化成给定若干线段,选出最少的线段覆盖所有区间,贪心即可。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    using namespace std;
    #define MAX 505
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    int d[4][2]={1,0,-1,0,0,1,0,-1};
    int a[MAX][MAX];
    int n,m,tot,ans;
    struct effect{int l,r;}p[MAX];
    bool operator<(effect a,effect b){if(a.l!=b.l)return a.l<b.l;return a.r>b.r;}
    bool vis[MAX][MAX];
    namespace check
    {
    	queue<int> Qx,Qy;
    	void bfs()
    	{
    		for(int i=1;i<=m;++i)Qx.push(1),Qy.push(i),vis[1][i]=true;
    		while(!Qx.empty())
    		{
    			int x=Qx.front(),y=Qy.front();Qx.pop(),Qy.pop();
    			for(int i=0;i<4;++i)
    			{
    				int xx=x+d[i][0],yy=y+d[i][1];
    				if(xx<1||yy<1||xx>n||yy>m)continue;
    				if(vis[xx][yy])continue;
    				if(a[xx][yy]>=a[x][y])continue;
    				vis[xx][yy]=true;
    				Qx.push(xx);Qy.push(yy);
    			}
    		}
    	}
    	void work()
    	{
    		bfs();int sum=0;
    		for(int i=1;i<=m;++i)
    			if(!vis[n][i])++sum;
    		if(sum){printf("0
    %d
    ",sum);exit(0);}
    		puts("1");
    	}
    }
    namespace Get
    {
    	void bfs(int Sx,int Sy)
    	{
    		memset(vis,0,sizeof(vis));queue<int> Qx,Qy;
    		Qx.push(Sx);Qy.push(Sy);vis[Sx][Sy]=true;
    		while(!Qx.empty())
    		{
    			int x=Qx.front(),y=Qy.front();Qx.pop(),Qy.pop();
    			for(int i=0;i<4;++i)
    			{
    				int xx=x+d[i][0],yy=y+d[i][1];
    				if(xx<1||yy<1||xx>n||yy>m)continue;
    				if(vis[xx][yy])continue;
    				if(a[xx][yy]>=a[x][y])continue;
    				vis[xx][yy]=true;
    				Qx.push(xx);Qy.push(yy);
    			}
    		}
    	}
    	void work()
    	{
    		for(int i=1;i<=m;++i)
    		{
    			bfs(1,i);int mx=0,mn=1e9;
    			for(int j=1;j<=m;++j)
    				if(vis[n][j])mx=j,mn=mn<j?mn:j;
    			if(mx<mn)continue;
    			p[++tot]=(effect){mn,mx};
    		}
    	}
    }
    int main()
    {
    	n=read();m=read();
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=m;++j)
    			a[i][j]=read();
    	check::work();Get::work();
    	sort(&p[1],&p[tot+1]);
    	int sum=0,r=0;
    	for(int i=1;i<=tot;++i)
    		if(p[i].r>p[i-1].r)p[++sum]=p[i];
    	tot=sum;
    	for(int i=1,j;i<=tot;i=j)
    	{
    		int nr=r;j=i;
    		while(j<=tot&&p[j].l<=r+1)nr=max(nr,p[j++].r);
    		ans+=1;r=nr;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    5_添加购物车 View+Con
    5_添加购物车 B+M
    5_添加购物车 D
    登录注册V
    bootstrap-标题
    h5整理--详解css的相对定位和绝对定位
    各大门户网站的css初始化代码
    九月二十八JS验证
    js函数和运算符
    4.1原始表达式 9/16
  • 原文地址:https://www.cnblogs.com/cjyyb/p/9917858.html
Copyright © 2011-2022 走看看