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;
}

posted on 2019-07-29 17:06  PPXppx  阅读(134)  评论(0编辑  收藏  举报