1、本题一次AC~用dfs做,需要记录的参数很多,用一个数组来保存输出序列。‘ ’的情况要特别处理。
2、USACO题库确实很不错,才做到2.3,我就觉得自己的水平比以前提高了很多,有点期待刷通关是什么样。
/*
ID:mrxy564
PROG:zerosum
LANG:C++
*/
#include<cstdio>
using namespace std;
int N;
char q[100];
void dfs(int last,int n,int m,char c,int cnt){
q[cnt]=m+'0';
if(m==N){
int ans;
if(c=='+') ans=last+n;
else if(c=='-') ans=last-n;
else if(c==' ') ans=last;
if(ans==0){
for(int i=0;i<=cnt;i++)
printf("%c",q[i]);
printf("\n");
}
return;
}
if(c=='+'){
q[cnt+1]=' ';
dfs(last+11*m+1,0,m+1,' ',cnt+2);
q[cnt+1]='+';
dfs(last+n,m+1,m+1,'+',cnt+2);
q[cnt+1]='-';
dfs(last+n,m+1,m+1,'-',cnt+2);
}
else if(c=='-'){
q[cnt+1]=' ';
dfs(last-11*m-1,0,m+1,' ',cnt+2);
q[cnt+1]='+';
dfs(last-n,m+1,m+1,'+',cnt+2);
q[cnt+1]='-';
dfs(last-n,m+1,m+1,'-',cnt+2);
}
else if(c==' '){
q[cnt+1]='+';
dfs(last,m+1,m+1,'+',cnt+2);
q[cnt+1]='-';
dfs(last,m+1,m+1,'-',cnt+2);
}
return;
}
int main(){
freopen("zerosum.in","r",stdin);
freopen("zerosum.out","w",stdout);
scanf("%d",&N);
dfs(0,1,1,'+',0);
return 0;
}
官方题解:
We can use a simple recursive depth first search to generate all the possible strings to be had by putting in a space, plus, or minus sign between each number.
Once we've generated each string, we evaluate it as an arithmetic sum and see if we get zero. If so, we print the string.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> FILE *fout; int n; /* evaluate the string s as arithmetic and return the sum */ int eval(char *s) { int term, sign, sum; char *p; sign = 1; term = 0; sum = 0; for(p=s; *p; p++) { switch(*p){ case '+': case '-': sum += sign*term; term = 0; sign = *p == '+' ? 1 : -1; break; case ' ': break; default: /* digit */ term = term*10 + *p-'0'; } } sum += sign*term; return sum; } /* * Insert + - or space after each number, and then * test to see if we get zero. The first k numbers have * already been taken care of. */ void search(char *s, int k) { char *p; if(k == n-1) { if(eval(s) == 0) fprintf(fout, "%s\n", s); return; } for(p=" +-"; *p; p++) { s[2*k+1] = *p; search(s, k+1); } } void main(void) { FILE *fin; int i; char str[30]; fin = fopen("zerosum.in", "r"); fout = fopen("zerosum.out", "w"); assert(fin != NULL && fout != NULL); fscanf(fin, "%d", &n); strcpy(str, "1 2 3 4 5 6 7 8 9"); str[2*n-1] = '\0'; /* chop string to only have first n numbers */ search(str, 0); exit(0); }