(簡單列舉)UVa 725
阿新 • • 發佈:2019-02-05
目錄
列舉所有沒必要,只需列舉其中的五位就可以計算出另一部分了,如果總位數超過10位,就可以終止枚舉了。
我的第一個程式碼是列舉每一位上的數從0-9逐一列舉(其中涉及到標記的回溯),第二個程式碼直接從組成的最小數到最大數開始列舉。最後只需判斷是否所有數字都不相同。
顯然第二個程式碼顯然效率更高。
程式碼1
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; int vis[10]; int main(){ int n,a1,b1,c1,d1,e1,tmp=-1; while(~scanf("%d",&n)){ if(n==0) break; if(tmp!=-1&&n!=tmp) printf("\n"); tmp=n; ll x,y; bool flag=false; memset(vis,0,sizeof(vis)); for(int a=0;a<10;a++){ vis[a]=1; for(int b=0;b<10;b++){ if(vis[b]==1) continue; vis[b]=1; for(int c=0;c<10;c++){ if(vis[c]==1) continue; vis[c]=1; for(int d=0;d<10;d++){ if(vis[d]==1) continue; vis[d]=1; for(int e=0;e<10;e++){ if(vis[e]==1) continue; vis[e]=1; y=e+d*10+c*100+b*1000+a*10000; x=y*n; if(x>=100000){ vis[e]=0; break; //continue; }else{ a1=x/10000; b1=(x%10000)/1000; c1=(x%1000)/100; d1=(x%100)/10; e1=x%10; if(vis[a1]==1){ vis[e]=0; continue; }else vis[a1]=1; if(vis[b1]==1){ vis[e]=0; vis[a1]=0; continue; }else vis[b1]=1; if(vis[c1]==1){ vis[e]=0; vis[a1]=0; vis[b1]=0; continue; }else vis[c1]=1; if(vis[d1]==1){ vis[e]=0; vis[a1]=0; vis[b1]=0; vis[c1]=0; continue; }else vis[d1]=1; if(vis[e1]==1){ vis[e]=0; vis[a1]=0; vis[b1]=0; vis[c1]=0; vis[d1]=0; continue; }else vis[e1]=1; flag=true; printf("%05ld / %05ld = %d\n",x,y,n); vis[a1]=0; vis[b1]=0; vis[c1]=0; vis[d1]=0; vis[e1]=0; } vis[e]=0; } vis[d]=0; } vis[c]=0; } vis[b]=0; } vis[a]=0; } if(!flag) printf("There are no solutions for %d.\n",n); } return 0; }
程式碼2
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; int vis[10]; int main(){ int n,a1,b1,c1,d1,e1,tmp=-1; while(~scanf("%d",&n)){ if(n==0) break; if(tmp!=-1&&n!=tmp) printf("\n"); tmp=n; ll x,y; bool flag=false; for(int i=1234;i<=98765;i++){ y=i; x=y*n; if(x>98765) break; //continue; memset(vis,0,sizeof(vis)); vis[y/10000]=1; if(vis[(y%10000)/1000]==1) continue; vis[(y%10000)/1000]=1; if(vis[(y%1000)/100]==1) continue; vis[(y%1000)/100]=1; if(vis[(y%100)/10]==1) continue; vis[(y%100)/10]=1; if(vis[y%10]==1) continue; vis[y%10]=1; if(vis[x/10000]==1) continue; vis[x/10000]=1; if(vis[(x%10000)/1000]==1) continue; vis[(x%10000)/1000]=1; if(vis[(x%1000)/100]==1) continue; vis[(x%1000)/100]=1; if(vis[(x%100)/10]==1) continue; vis[(x%100)/10]=1; if(vis[x%10]==1) continue; vis[x%10]=1; flag=true; printf("%05ld / %05ld = %d\n",x,y,n); } if(!flag) printf("There are no solutions for %d.\n",n); } return 0; }
程式碼3 (藉助sprintf進行列舉,省時又省力)
sprintf用於將格式化的資料寫入字串,標頭檔案:#include<stdio.h>。
sprintf將求的數轉化成字串,然後進行排序,和"9876543210"進行比較,從而判斷所有數字都各不相同。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; bool cmp(char a, char b) { return a>b; } char ans[11]="9876543210"; char s[11]; int main() { int n,y,tmp=-1; bool flag=false; while(~scanf("%d", &n)) { if(n==0) break; if(tmp!=-1&&n!=tmp) printf("\n"); tmp=n; flag=false; for(int i=1234; i<=98765; i++) { y=n*i; if(y>98765) break; if(i<10000) sprintf(s, "%d%d%d", 0, i,y); else sprintf(s, "%d%d", i,y); sort(s,s+10,cmp); if(strcmp(s,ans)==0) { printf("%05d / %05d = %d\n",y,i,n); flag=true; } } if(!flag) printf("There are no solutions for %d.\n", n); } return 0; }