zoukankan      html  css  js  c++  java
  • USACO Section 1.4(有技巧的枚举)

    等差数列 Arithmetic Progressions

    题意:一个等差数列是一个能表示成(a, a+b, a+2b,..., a+nb (n=0,1,2,3,...))的数列.在这个问题中a是一个非负的整数,b是正整数。写一个程序来找出在双平方数集合(双平方数集合是所有能表示成p的平方 + q的平方的数的集合,其中p和q为非负整数)S中长度为n的等差数列.

    分析:先求出集合S,然后对于一个等差数列,我们只要枚举出前面两个数,就可以得到公差d,即可以推出整个数列,然后对于推出来的每一项,我们判断是否在集合S之中即可.然后有一个小优化,就是当我们枚举完前两项后,我们直接先判断最大项如果比集合S中的最大值大,说明此次枚举不合法.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=200005;
    int S[N],tong[N];
    struct ppx{int a,b;}ans[N];
    inline bool cmp(const ppx &x,const ppx &y){return x.b==y.b?x.a<y.a:x.b<y.b;}
    int main(){
    	int n=read(),m=read(),tot=0,Ans=0;
    	for(int i=0;i<=m;++i)
    		for(int j=0;j<=i;++j){
    			if(!tong[i*i+j*j])S[++tot]=i*i+j*j;
    			tong[S[tot]]=1;
    		}
    	sort(S+1,S+tot+1);
    	for(int i=1;i<=tot-n+1;++i)
    		for(int j=i+1;j<=tot-n+2;++j){
    			int d=S[j]-S[i],p=S[j],T=n-2,bj=1;
    			if(p+T*d>S[tot])break;
    			while(T--){
    				p+=d;
    				if(!tong[p]){bj=0;break;}
    			}
    			if(bj)ans[++Ans].a=S[i],ans[Ans].b=d;
    		}
    	if(!Ans){puts("NONE");return 0;}
    	sort(ans+1,ans+Ans+1,cmp);
    	for(int i=1;i<=Ans;++i)
    		printf("%d %d
    ",ans[i].a,ans[i].b);
        return 0;
    }
    

    母亲的牛奶 Mother's Milk

    题意:农民约翰有三个容量分别是A,B,C升的桶,A,B,C分别是三个从1到20的整数, 最初,A和B桶都是空的,而C桶是装满牛奶的。有时,农民把牛奶从一个桶倒到另一个桶中,直到被灌桶装满或原桶空了。当然每一次灌注都是完全的。由于节约,牛奶不会有丢失。写一个程序去帮助农民找出当A桶是空的时候,C桶中牛奶所剩量的所有可能性。

    分析:对于每一个状态,我们只有六种操作,即a给b,a给c,b给a,b给c,c给a,c给b,我们直接DFS穷举所有状态.然后类似于记忆化搜索,我们开一个visit[a][b][c]记录当前状态是否访问过,提高搜索效率.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    int A,B,C,bj[25],visit[25][25][25];
    inline void dfs(int a,int b,int c){
    	if(visit[a][b][c])return;
    	if(a==0)bj[c]=1;
    	visit[a][b][c]=1;
    	if(c){
    		if(a<A){
    			int now=min(A,a+c);
    			dfs(now,b,c-now+a);
    		}
    		if(b<B){
    			int now=min(B,b+c);
    			dfs(a,now,c-now+b);
    		}
    	}
    	if(b){
    		if(a<A){
    			int now=min(A,a+b);
    			dfs(now,b-now+a,c);
    		}
    		if(c<C){
    			int now=min(C,b+c);
    			dfs(a,b-now+c,now);
    		}
    	}
    	if(a){
    		if(b<B){
    			int now=min(B,a+b);
    			dfs(a-now+b,now,c);
    		}
    		if(c<C){
    			int now=min(C,a+c);
    			dfs(a-now+c,b,now);
    		}
    	}
    }
    int main(){
    	A=read(),B=read(),C=read();
    	dfs(0,0,C);
    	for(int i=0;i<=20;++i)if(bj[i])printf("%d ",i);//记得从0开始
    	printf("
    ");
        return 0;
    }
    
    
  • 相关阅读:
    CF 436D 最小生成树
    HDU 1847 博弈
    ZOJ 3666 博弈 SG函数
    zoj3675 BFS+状态压缩
    HDU 4734 F(x) 数位DP
    HDU 3709 Balanced Number 数位DP
    HDU 3555 数位DP
    HDU 4336 Card Collector
    HDU4340 Capturing a country DP
    CF 351A
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11265023.html
Copyright © 2011-2022 走看看