一、題目概述:
A、Coin Change(暴力求解、動態規劃)
B、Fibbonacci Number(遞推求解)
C、Max Num(排序、比較)
D、單詞數(字符串比較、庫函數運用)
E、無限的路(平面幾何)
F、疊筐(規律輸出)
二、解題報告:
A、Coin Change
給一個錢的總金額,求出用100個以內的50分、25分、10分、5分、1分硬幣拼成該金額的不同拼法。
直接暴力,打表什麼的都是浮雲。開始總覺得用暴力求解顯得自己沒風度,不夠高端霸氣上檔次。當面臨各種WA時,什麼都是浮雲,唯有AC纔是王道。
用i,j,k,x,y分別表示50分、25分、10分、5分、1分硬幣的數量,用四重循環直接暴力(不用五層。剩下的變量直接可以求得)。當y=n-x*5-k*10-j*25-i*50;並且y不小於0,硬幣總數不大於100的時候,表示這種拼法是可以的,計數變量sum自加一,最後直接輸出計數變量即可。
#include<iostream> #include<cstring> #include<cstdio> using namespace std; int main() { int n; int i,j,k,x,y; while(cin>>n) { __int64 sum=0; for(i=0; i<=n/50; i++) //50分的硬幣i個 for(j=0; j<=n/25; j++) //25分的硬幣j個 for(k=0; k<=n/10; k++) //10分的硬幣k個 for(x=0; x<=n/5; x++) //5分的硬幣x個 { y=n-x*5-k*10-j*25-i*50; //一分的硬幣y個 if(y>=0&&i+j+k+x+y<=100)sum++; //滿足要求,這種拼法是可以的 } cout<<sum<<endl; } return 0; }
B、Fibbonacci Number
沒什麼好講的,直接用公式來算就好了。
不過要注意兩點:
(1)先打表,後面要用到的話,直接輸出即可。避免超時。
(2)要用64爲位int,題目最大輸出第50個斐波那契數,該數超出32位int的存儲範圍。否則,數據溢出造成WA。
#include<iostream> using namespace std; int main() { __int64 f[55]; int i,n; f[0]=0; f[1]=1; for(i=2;i<55;i++)f[i]=f[i-1]+f[i-2]; //直接打表 while(cin>>n&&n!=-1)cout<<f[n]<<endl; //直接按表輸出 return 0; }
C、Max Num
簡單題,直接比較就好了。
t組數據,每組數據n個,然是n個數據,求n個數據中的最大值。
對於每一組數據,用一個初始值爲0(輸入的值都不小於0)的max比較處理。逐個輸入n個數,每個數和max比較,要是比max大,就替換max的值。後面直接輸出max的值就好了。注意用double處理數據。
#include<iostream> #include<cstdio> using namespace std; int main() { int t,n; double x,max; cin>>t; while(t--) { max=0; cin>>n; while(n--) { cin>>x; if(x>max)max=x; //直接比較替換 } printf("%.2lf\n",max); //直接輸出 } return 0; }
D、單詞數
稍難的題目,數單詞不難,要是常規句式(沒有空格),直接數空格就好,單詞數=空格數+1;
問題是,這裏要的是不同的單詞的種類(句子中還可能有多個空格隔開兩個單詞,句子的前後端也可能有空格,一個回車結束一個句子)。一般的藥已經治不了他了,要想做,不放棄治療,只能用“抗生素”了。用到sscanf,從字符數組中讀取字符串,用到set容器判斷該單詞前面是否出現過。
(1)用gets輸入數據,一個gets結束就代表一個案例輸入完成(最好把用來存儲的數組開大點)。
(2)用sscanf(需要起始位置)從前到後從數組中讀出字符串(遇到空格讀取就結束),人工跳過空格。
(3)用set判斷先下讀取的單詞是否在前面出現過,要是沒有出現過,直接壓入容器,計數變量(記得初始化啊)加1。否則直接跳過。
(4)最後輸出計數變量的值即可。
#include<stdio.h> #include<string.h> #include<iostream> #include<cstring> #include<string> #include<set> using namespace std; char f[100000000]; int main() { //freopen("in.txt","r",stdin); __int64 n; int i,j; char a[1000]; while(gets(f)&&f[0]!='#') //輸入案例數據,遇到“#”時,程序結束 { n=0; //計數變量初始化 set<string> s; //定義容器s int len=strlen(f); //求出輸入數據的長度 for(i=0; i<len; i++) //“逐個”檢索 { if(f[i]==' ')continue; //跳過空格 sscanf(f+i,"%s",a); //讀取字符串 if(!s.count(a)) //判斷字符串是否在前面出現過(沒有出現過) { n++; //計數變量加1 s.insert(a); //壓入容器 } i=i+strlen(a)-1; //跳過已處理的字符串 } cout<<n<<endl; //輸出計數變量即可 } return 0; }
E、無限的路
集合題,鬱悶了很久。所有的點都在直線x+y=b上。。。
先處理最特殊的(0,0)點
後面求的時候分成4段
(1)前殘餘段
(2)中間直線x+y=b的線段總長度
(3)中間連接(2)中直線的線段的總長度
(4)後殘餘短
#include<stdio.h> #include<math.h> #include<algorithm> using namespace std; double f(int x,int y) { return sqrt(x*x+y*y); } int main() { int t; int x,y; int x1,y1,x2,y2; double l; int i,j; scanf("%d",&t); while(t--) { l=0; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); x=x1+y1; y=x2+y2; if(y<x) { swap(x1,x2); swap(y1,y2); } if(x1==0&&y1==0) { l+=1; x1=0; y1=1; } if(x1+y1==x2+y2) l+=f(x1-x2,y1-y2); else { x=x1+y1; y=x2+y2; for(i=x+1; i<y; i++) l+=f(i,i); for(i=x; i<y; i++) l+=f(i,i+1); l+=f(y1,y1); l+=f(x2,x2); } printf("%.3lf\n",l); } return 0; }
F、疊筐
就是圈一圈的輸出的意思,用二維數組存儲圖案,一圈一圈的賦值。從裏到外,一圈賦完後改變填充值。
注意n=1時的特殊處理
注意輸出格式:
(1)案例間要換行
(2)“剪角”
#include<stdio.h> int main() { //freopen("in.txt","r",stdin); int n,i,j; char a[2],b[2],c; char pi[85][85]; int f=0; while(scanf("%d%s%s",&n,a,b)!=EOF) { if(f)printf("\n"); //案例間的換行 if(n==1) //要是隻有1個 printf("%c\n",a[0]); else { c=a[0]; for(i=n/2; i>=0; i--) //從裏到外(填充) { for(j=i; j<=n-i-1; j++) { pi[i][j]=c; //上面一行 pi[n-i-1][j]=c; //下面一行 pi[j][i]=c; //左邊一列 pi[j][n-i-1]=c; //右邊一列 } if(c==a[0])c=b[0]; //更換“填充物” else c=a[0]; } //pi[n/2][n/2]=a[0]; for(i=0; i<n; i++) { for(j=0; j<n; j++) { if((i==0&&j==0)||(i==0&&j==n-1)||(i==n-1&&j==0)||(i==n-1&&j==n-1)) //“剪角” printf(" "); else printf("%c",pi[i][j]); } printf("\n"); } } f=1; } return 0; }