問題 B: 習題6-12 解密 時間限制: 1 Sec 內存限制: 12 MB 提交: 50 解決: 31 外部導入 提交狀態討論版 題目描述 有一行電文,已按以下規律譯成密碼: A-->Z a-->z B-->Y b-->y C-->X c-->x ...... ...... 即第一個字母變成第26個字母,第i個字母變成第(26-i+1)個字母,非字母字符不變。要求根據密碼譯回原文,並輸出。 輸入 輸入一行密文 輸出 解密後的原文,單獨佔一行。 樣例輸入 Copy ZYX123zyx 樣例輸出 Copy ABC123abc
int main() { string s; while(cin>>s) { int len,i; len=s.size(); for(i=0;i<len;i++) { if(s[i]=='Z') { s[i]='A'; } else if(s[i]=='z') { s[i]='a'; } else if(s[i]>='B'&&s[i]<='Y') { s[i]=155-s[i]; } else if(s[i]>='b'&&s[i]<='y') { s[i]=219-s[i]; } } cout<<s<<endl; } return 0; }
問題 C: 數字三角形之備忘錄法 時間限制: 1 Sec 內存限制: 128 MB 提交: 2 解決: 0 201501010119 提交狀態討論版 題目描述 以下圖所示的數字三角形,從三角形的頂部到底部有不少條不一樣的路徑。對於每條路徑,把路徑上面的數加起來能夠獲得一個和,和最大的路徑稱爲最佳路徑。編寫一個程序求出最佳路徑上的數字之和。 【使用備忘錄法實現】 7 3 8 8 1 2 2 7 4 4 4 5 2 6 5 輸入 多組樣例輸入,每組第一行輸入三角形的層數n,接下來n行輸入三角形。 輸出 輸出最佳路徑上的數字之和。 樣例輸入 Copy 2 1 1 2 3 1 1 2 1 2 3 樣例輸出 Copy 3 6 提示 路徑上的每一步只能從一個數走到下一層上和它最近的左邊的數或者右邊的數。
using namespace std; int a[105][105],p[105][105],n; int s(int i,int j) { if(p[i][j]>=0) //若是計算過了 return p[i][j]; if(i==n+1) //p雖然是第i行,可是最下面一行已經算過了,因此這是結束遞歸的條件 return 0; else return p[i][j]=a[i][j]+max(s(i+1,j),s(i+1,j+1)); //規律,a[i][j](處於i,j位置的數組元素a,)加上它正下方的元素和斜下方的元素取最大=》最優子結構,從一開始就取最大值 } int main() { while(cin>>n) { for(int i=1;i<=n;i++) //注意輸入的數組爲三角形狀,因此不要搞混i,j的取值 for(int j=1;j<=i;j++) cin>>a[i][j]; memset(p,-1,sizeof(p)); //把p置爲-1 s(1,1); //下標從1開始 cout<<p[1][1]<<endl; } return 0; }
以上爲備忘錄法;數組
p數組用來記錄是否算過路徑;由於最初的想法就是從最上部一直遞歸到最下面,可是這樣時間複雜度很大,因此用一個數組來存是否算過這條路;spa
遞歸從(1,1)開始,可是一直遞歸到最下面那一層,當遞歸結束的時候開始返回上一層(計算結果),可是在返回上一層的時候不少數咱們是重複計算過的,因此咱們須要一個數組來備忘 記錄咱們是否算過這個數,code
動態規劃法blog
從底向上找最優解遞歸
int a[105][105],p[105][105],n; int s() { for(int j=1;j<=n;j++) p[n][j]=a[n][j]; //把a最後一行的值給p的最後一行 for(int i=n-1;i>=1;i--) //自底向上 for(int j=1;j<=i;j++) p[i][j]=a[i][j]+max(p[i+1][j],p[i+1][j+1]); //其實從備忘錄法已經能夠猜到dp規律了 return 0; } int main() { while(cin>>n) { for(int i=1;i<=n;i++) for(int j=1;j<=i;j++) cin>>a[i][j]; memset(p,-1,sizeof(p)); s(); cout<<p[1][1]<<endl; } return 0; }