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\n",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("\n");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/PPXppx/p/11265023.html
今日推荐