hdu1015 Safecracker —— 回溯
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1015
代码1:
#include<stdio.h>//hdu1015 #include<string.h> #include<math.h> #include<stdlib.h> double tg; int len; char a[20],b[20];//a存输入的字母,从0开始存。 b存目标字母,从1开始。 int cmp(const void*a, const void*b) { return *(char*)b-*(char*)a; } int solve(double sum,int n)//为什么int sum就不行呢? { if(n==6) { if(sum==tg) return 1; else return 0; } for(int i = 0;i<len; i++) { int j; for(j = 1;j<n;j++)//寻找是否与已存的字母重复 if(a[i]==b[j]) break; if(j==n)//若不重复,则存入现在的b[n]中 { double sum1 = sum;//记录原先的sum值,若不符合条件,则将其值还原 b[n] = a[i]; if(n%2) sum += pow(b[n]-64,n); else sum -= pow(b[n]-64,n); if(solve(sum,n+1)) return 1; sum = sum1;//在递归的出口将sum还原为之前的值,这样才不会妨碍下一个字母的操作 } } return 0; } int main() { while(scanf("%lf %s",&tg,a)==2 && (tg || strcmp(a,"END"))) { len = strlen(a); qsort(a,len,sizeof(a[0]),cmp);//将输入的字母排序,以便最大字典序输出 if(solve(0,1)) puts(b+1);//由于b从1开始存,所以输入的地址要加一个单位 else puts("no solution"); } return 0; }
代码2:
#include<cstdio>//hdu1015 方法2 #include<cstring> #include<cmath> #include<cstdlib> int tg; int len; char a[20],b[20]; int cmp(const void*a, const void*b) { return *(char*)b-*(char*)a; } int solve(int n) { if(n==6) { double sum = pow(b[1]-64,1)-pow(b[2]-64,2) + pow(b[3]-64,3)- pow(b[4]-64,4)+ pow(b[5]-64,5); if( sum == tg) return 1; else return 0; } for(int i = 0;i<len; i++) { int j; for(j = 1;j<n;j++) if(a[i]==b[j]) break; if(j==n) { b[n] = a[i]; if(solve(n+1)) return 1; } } return 0; } int main() { while(scanf("%d %s",&tg,a)==2 && (tg || strcmp(a,"END"))) { len = strlen(a); qsort(a,len,sizeof(a[0]),cmp); if(solve(1)) puts(b+1); else puts("no solution"); } return 0; }