Topcoder 658 650 point
Topcoder 658 div2 500 加强版
不过给了<=20,暴力肯定不行。
然后想DP方程,先二分可能需要的最大次数mid;
然后根据 mid 构造 DP方程。
假设x[i]需要 x个9 ,y个3,z个1,x*9+y*3+z>=x[i];
然后求出dp[n][[x]][y][z]<=mid 是否 符合。
转移方程为:dp[i+1][n9+m9][m3+n3]=min(dp[i+1][n9+m9][n3+m3],dp[i][n9][n3]+max(0,x[i]-9*m9-3*m3));
(i<n,m9+n9<=mid,m3+n3<=mid)
这里是5维
1 #include <iostream> 2 #include <cstdlib> 3 #include <algorithm> 4 #include <fstream> 5 #include <cstdio> 6 #include <cmath> 7 #include <cstring> 8 #include <string> 9 #include <ctime> 10 #include <queue> 11 #include <stack> 12 #include <vector> 13 #include <map> 14 #include <deque> 15 #include <set> 16 17 using namespace std; 18 19 int dp[22][151][151]; 20 21 class Mutalisk 22 { 23 public: 24 int minimalAttacks(vector <int> x) 25 { 26 27 int r=150,l=0; 28 int n=x.size(); 29 for (int _=1;_<20;_++) 30 { 31 int mid=(l+r)>>1; 32 memset(dp,1,sizeof(dp)); 33 dp[0][0][0]=0; 34 35 for (int i=0;i<n;i++) 36 for (int n9=0;n9<=mid;n9++) 37 for (int n3=0;n3<=mid;n3++) 38 { 39 if (dp[i][n9][n3]>mid ) continue; 40 41 for (int m9=0;m9*9<=x[i]+8&&m9+n9<=mid;m9++) 42 for (int m3=0;m3*3+m9*9<=max(m9*9,x[i]+2)&&m3+n3<=mid;m3++) 43 { 44 if (m9+m3+max(0,x[i]-9*m9-3*m3)>mid) continue; 45 dp[i+1][n9+m9][m3+n3]=min(dp[i+1][n9+m9][n3+m3],dp[i][n9][n3]+max(0,x[i]-9*m9-3*m3)); 46 } 47 } 48 49 int ok=0; 50 for (int n9=0;!ok&&n9<=mid;n9++) 51 for (int n3=0;!ok&&n3<=mid;n3++) 52 if (dp[n][n9][n3]<=mid) 53 { 54 ok=1; 55 } 56 57 if (ok) r=mid; 58 else l=mid; 59 } 60 return r; 61 } 62 }; 63 64 int main() 65 { 66 int n; 67 cin>>n; 68 vector<int> p; 69 for (int i=1;i<=n;i++) 70 { 71 int x; 72 cin>>x; 73 p.push_back(x); 74 } 75 Mutalisk q; 76 cout<<q.minimalAttacks(p)<<endl; 77 return 0; 78 }
状态,需要剪枝。
随性Code