动态规划专题
一、简单基础dp
1、递推:
1 #include <iostream> 2 #include <map> 3 #include <stack> 4 #include <deque> 5 #include <queue> 6 #include <vector> 7 #include <set> 8 #include <algorithm> 9 #include <cstring> 10 #include <cstdio> 11 using namespace std; 12 const int N=105; 13 int t, n; 14 int tow[N][N]; 15 void cal() 16 { 17 for(int i=n-2; i>=0; i--) 18 for(int j=0; j<=i; j++) 19 tow[i][j]+=max(tow[i+1][j],tow[i+1][j+1]); 20 } 21 int main() 22 { 23 //freopen("input.txt", "r", stdin); 24 cin>>t; 25 while(t--) 26 { 27 memset(tow, 0, sizeof(tow)); 28 cin>>n; 29 for(int i=0; i<n; i++)//输入 30 for(int j=0; j<=i; j++) 31 scanf("%d",&tow[i][j]); 32 cal(); 33 cout<<tow[0][0]<<endl; 34 } 35 return 0; 36 }
hdu 2018 母牛的故事 每年的牛数量=去年的已成年牛*2 + 今年刚好成年的牛*2 + 还未成年的牛。 (假设牛成年时立刻生牛仔)
1 #include <iostream> 2 #include <map> 3 #include <stack> 4 #include <deque> 5 #include <queue> 6 #include <vector> 7 #include <set> 8 #include <algorithm> 9 #include <cstring> 10 #include <cstdio> 11 using namespace std; 12 const int N=56; 13 int t; 14 int num[N]; 15 int chi[N]; 16 int bir[N]; 17 void cal() 18 { 19 num[1]=1;num[2]=2;num[3]=3; 20 chi[2]=1;chi[3]=2; 21 bir[2]=1;bir[3]=1; 22 for(int i=4; i<N; i++) 23 { 24 int tmp1=num[i-1]-chi[i-1]; 25 int tmp2=chi[i-1]-bir[i-3]; 26 num[i]= (tmp1<<1) + (bir[i-3]<<1) + tmp2 ; //已成年*2 + 刚好成年*2 + 未成年 27 chi[i]= tmp1 + bir[i-3] + tmp2 ;//已成年+刚好成年+未成年 28 bir[i]= tmp1 + bir[i-3] ;//已成年+刚好成年 29 //以上文字表示的全是量,并不是意思。 30 } 31 32 } 33 int main() 34 { 35 //freopen("input.txt", "r", stdin); 36 cal(); 37 while(cin>>t,t) 38 cout<<num[t]<<endl; 39 return 0; 40 }
hdu 2044 一只小蜜蜂 完全是fabonacci
1 #include <iostream> 2 #include <map> 3 #include <stack> 4 #include <deque> 5 #include <queue> 6 #include <vector> 7 #include <set> 8 #include <algorithm> 9 #include <cstring> 10 #include <cstdio> 11 12 using namespace std; 13 const int N=51; 14 int t, tmp1, tmp2; 15 long long fab[N]; 16 void cal() 17 { 18 fab[0]=fab[1]=1; 19 for(int i=2; i<N; i++) 20 fab[i]=fab[i-1]+fab[i-2]; 21 22 } 23 int main() 24 { 25 //freopen("input.txt", "r", stdin); 26 cal(); 27 cin>>t; 28 while(t--) 29 { 30 cin>>tmp1>>tmp2; 31 cout<<fab[tmp2-tmp1]<<endl; 32 } 33 34 return 0; 35 }
hdu 2050 折线分割平面 解法看此博客 http://blog.sina.com.cn/s/blog_76eabc150100swg8.html
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 const int N=10002; 5 long long a[N]; 6 void cal() 7 { 8 a[0]=1;a[1]=2;a[2]=7; 9 for(int i=3; i<N; i++) 10 a[i]=(4*i-3)+a[i-1]; 11 } 12 int main() 13 { 14 //freopen("input.txt", "r", stdin); 15 cal(); 16 int t, i; 17 cin>>t; 18 while(t--) 19 { 20 scanf("%d",&i); 21 printf("%d\n",a[i]); 22 } 23 return 0; 24 }
B.working out 用dp预处理4个角,再穷举除了边框外所有的格子,每格有两种可能,最后求出最大。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 #define ll long long 6 const int N=1002; 7 long long a[N][N]; 8 9 struct pos 10 { 11 ll lef_top; 12 ll rig_top; 13 ll lef_bot; 14 ll rig_bot; 15 }dp[N][N]; 16 int n, m; 17 18 void cal_dp() 19 { 20 //左上 21 dp[0][0].lef_top=a[0][0]; 22 for(int i=1; i<m; i++) dp[0][i].lef_top=dp[0][i-1].lef_top+a[0][i]; 23 for(int i=1; i<m; i++) dp[i][0].lef_top=dp[i-1][0].lef_top+a[i][0]; 24 //左下 25 dp[n-1][0].lef_bot=a[n-1][0]; 26 for(int i=1; i<m; i++) dp[n-1][i].lef_bot=dp[n-1][i-1].lef_bot+a[n-1][i]; 27 for(int i=n-2; i>=0; i--) dp[i][0].lef_bot=dp[i+1][0].lef_bot+a[i][0]; 28 //右上 29 dp[0][m-1].rig_top=a[0][m-1]; 30 for(int i=m-2; i>=0; i--) dp[0][i].rig_top=dp[0][i+1].rig_top+a[0][i]; 31 for(int i=1; i<n; i++) dp[i][m-1].rig_top=dp[i-1][m-1].rig_top+a[i][m-1]; 32 //右下 33 dp[n-1][m-1].rig_bot=a[n-1][m-1]; 34 for(int i=m-2; i>=0; i--) dp[n-1][i].rig_bot=dp[n-1][i+1].rig_bot+a[n-1][i]; 35 for(int i=n-2; i>=0; i--) dp[i][m-1].rig_bot=dp[i+1][m-1].rig_bot+a[i][m-1]; 36 37 for(int i=1; i<n; i++) //左上 38 { 39 for(int j=1; j<m; j++) 40 { 41 dp[i][j].lef_top=max(dp[i][j-1].lef_top, dp[i-1][j].lef_top)+a[i][j]; 42 } 43 } 44 45 for(int i=n-2; i>=0; i--) //左下 46 { 47 for(int j=1; j<m; j++) 48 { 49 dp[i][j].lef_bot=max(dp[i][j-1].lef_bot, dp[i+1][j].lef_bot)+a[i][j]; 50 } 51 } 52 53 for(int i=1; i<n; i++) //右上 54 { 55 for(int j=m-2; j>=0; j--) 56 { 57 dp[i][j].rig_top=max(dp[i][j+1].rig_top, dp[i-1][j].rig_top)+a[i][j]; 58 } 59 } 60 61 for(int i=n-2; i>=0; i--) 62 { 63 for(int j=m-2; j>=0; j--) 64 { 65 dp[i][j].rig_bot=max(dp[i][j+1].rig_bot, dp[i+1][j].rig_bot)+a[i][j]; 66 } 67 } 68 69 } 70 71 long long enu() 72 { 73 //对非外环的所有格子进行穷举 74 long long ans=0; 75 for(int i=1; i<n-1; i++) 76 { 77 for(int j=1; j<m-1; j++) 78 { 79 //左上:往右 左下:往上 //左上:往下 左下:往右 80 long long tmp1=dp[i][j-1].lef_top+dp[i][j+1].rig_bot+dp[i+1][j].lef_bot+dp[i-1][j].rig_top; 81 long long tmp2=dp[i-1][j].lef_top+dp[i+1][j].rig_bot+dp[i][j-1].lef_bot+dp[i][j+1].rig_top; 82 //cout<<tmp1<<" "<<tmp2<<endl; 83 if( ans<max(tmp1,tmp2) ) 84 ans=tmp1>tmp2?tmp1:tmp2; 85 86 } 87 } 88 return ans; 89 } 90 91 int main() 92 { 93 //freopen("input.txt", "r", stdin); 94 while(cin>>n>>m) 95 { 96 memset(dp,0,sizeof(dp)); 97 for(int i=0; i<n; i++) 98 for(int j=0; j<m; j++) 99 scanf("%d",&a[i][j]); 100 cal_dp(); 101 cout<<enu()<<endl;; 102 } 103 return 0; 104 }
UVA10328 Coin Toss dp带限制的递推,大数
HDU Number String 排列组合数问题,题解戳代码。题不错,技巧性很强。
HDU The King’s Ups and Downs 排列组合数问题,题解戳代码
+代码在此
二、背包专题
UVA-624 CD 要记录路径的常规01背包
HDU 2955 Robberies 背包容量是double型,寻找其他背包容量。01背包变形。
HDU 2602 Bone Collector 最常规的01背包。
POJ 3624 Charm Bracelet 最常规的01背包。