USACO官方给的是暴力搜索,逐个判断的思路,不涉及搜索算法需要的判重。
我这个题解主要是用的深搜思路,用一个vector数组,精确构造满足题意的组合,然后使用一个1,000,000大的visit数组,记录是否访问过,使用空间换取时间。
/*
ID: cjn77881
LANG: C++
TASK: combo
*/
#include <stdio.h>
int N,x1,x2,x3,y1,y2,y3,idx,ans,a[3],vector[5]={-2,-1,0,1,2};
bool v[1000001];
void deal(int &x){
if (x>=N) x-=N;
if (x<0) x+=N;
}
int hash(int *a){ //简单构造的哈希函数,用空间换时间
return (a[0]*10000+a[1]*100+a[2]);
}
void dfs(int *a,int depth){
if (depth==3){
idx = hash(a);
if (!v[idx]){
ans++;
v[idx]=true;
// for (int i=0;i<3;i++) printf("%d ",a[i]); printf("\n");
}
return;
}
for (int i=0;i<5;i++) {
a[depth]+=vector[i]; deal(a[depth]);
dfs(a,depth+1);
a[depth]-=vector[i]; deal(a[depth]); //进行下一项前,先将a[depth]恢复原值
}
return;
}
int main(){
FILE *fin = fopen("combo.in","r");
FILE *fout = fopen("combo.out","w");
fscanf(fin,"%d\n",&N);
fscanf(fin,"%d %d %d",&x1,&x2,&x3);
fscanf(fin,"%d %d %d",&y1,&y2,&y3);
if (N==1){ //只有一个选项时,没必要通过vector函数向左右移位了
vector[0]=0; vector[1]=0; vector[3]=0; vector[4]=0;
}
if (N==2){ //只有两个选项时,通过vector函数向左右移位,一位就足矣
vector[0]=0; vector[4]=0;
}
x1--; x2--; x3--;
y1--; y2--; y3--;
a[0]=x1; a[1]=x2; a[2]=x3;
dfs(a,0);
a[0]=y1; a[1]=y2; a[2]=y3;
dfs(a,0);
printf("%d\n",ans);
fprintf(fout,"%d\n",ans);
return 0;
}