很顯然,一套系統最多攔截導彈數即爲導彈高度的最長不上升子序列,而須要系統數即爲最長降低子序列。ios
直接\(O(nlogn)\)解決便可。spa
\(Code:\)設計
#include<cstdio> #include<algorithm> #include<iostream> using namespace std; const int N=1e5+5; int n,a[N],b[N],k1,k2,c[N]; int main() { while(~scanf("%d",&a[++n]));--n; b[++k1]=a[1],c[++k2]=a[1]; for(int i=2;i<=n;++i) { if(a[i]<=b[k1]) b[++k1]=a[i]; else { int pos=upper_bound(b+1,b+k1+1,a[i],greater<int>())-b; b[pos]=a[i]; } if(a[i]>c[k2]) c[++k2]=a[i]; else { int pos=lower_bound(c+1,c+k2+1,a[i])-c; c[pos]=a[i]; } } printf("%d\n%d",k1,k2); return 0; }
簡單的模擬,要注意特判\(n > 10\)的時候。code
\(Code:\)ci
#include<iostream> #include<cstring> #include<string> using namespace std; int x,n,sum,a[1001]; string s; inline bool hw(int n) { for(int i=1;i<=n/2;i++) if(a[i]!=a[n-i+1]) return false; return true; } inline int jia(int n) { int c[1001]={0}; for(int i=1;i<=n;i++) { c[i]+=a[i]+a[n-i+1]; c[i+1]+=c[i]/x; c[i]%=x; } if(c[n+1]) n++; for(int i=n;i>=1;i--) a[i]=c[i]; return n; } int main() { cin>>x>>s;n=s.size(); for(int i=1;i<=n;++i) { if(s[i-1]<65) a[i]=s[i-1]-'0'; else a[i]=s[i-1]-55;//特判字母 } while(sum<=30) { if(hw(n)) { printf("STEP=%d",sum); return 0; } ++sum,n=jia(n); } puts("Impossible!"); }
仍然是模擬,還加了點貪心。get
在一個加油站所須要加的油,就是可以支持它到達下一個油價比它低的加油站的量string
若是在這個加油站即便加滿油,都不能到達一個比它油價低的加油站,就把油箱加滿,前往可以到達的加油站中油價最低的那個(貪心地想,這種決策確定是能省錢的)it
\(Code:\)io
#include<cstdio> #include<algorithm> using namespace std; #define db double int n; db D1,v,D2,P[233],D[233]; db solve() { db s=v*D2;//車能開的距離 db sum=(1.0*D[1]/D2)*P[0];//總費用 db sumD=D[1]; if(D[1]>s) return -1; db now=P[0];//設爲當前使用的油價 for(int i=1;i<=n;++i) if(P[i]-P[i-1]>s) return -1; int i=1; while(i<=n) { if(P[i]>=now) { sumD+=D[i+1]-D[i]; if(sumD>s) { sum+=(1.0*(s-(sumD-(D[i+1]-D[i])))/D2)*now; now=P[i],sumD=sumD-s; sum+=(1.0*sumD/D2)*now; } else sum+=(1.0*(D[i+1]-D[i])/D2)*now; ++i; } else now=P[i],sumD=0; } return sum; } int main() { scanf("%lf%lf%lf%lf%d",&D1,&v,&D2,&P[0],&n); for(int i=1;i<=n;i++) scanf("%lf%lf",&D[i],&P[i]); D[n+1]=D1; db sum=solve(); if(sum<0) puts("No Solution"); else printf("%.2lf\n",sum); return 0; }
很顯然是個爆搜題,不過爆搜的範圍怎麼肯定呢?
咱們發現,若是令$p = \(選完上一個數可拼成的面值,則當前數的範圍爲\)[上一個數 + 1 , p + 1]\((這個道理仔細想一下就明白了) 肯定最大面值的問題,就能夠用徹底揹包來解決啦! 定義\)dp[i]\(爲拼成\)i\(最少須要的郵票數,則狀態轉移方程爲:\)dp[i] = min(dp[i],dp[i - a[j]] + 1)$
\(Code:\)class
#include<cstdio> #include<vector> #include<cstring> #include<algorithm> using namespace std; const int inf=0x3f3f3f3f; #define rg register vector<int>ans,temp; int n,k,dp[2333],Ans; inline int f() { memset(dp,inf,sizeof dp),dp[0]=0; for(rg int i=1;;++i) { for(rg int j=0;j<(int)temp.size() && temp[j]<=i;++j) dp[i]=min(dp[i],dp[i-temp[j]]+1); if(dp[i]>n) { if(i>Ans+1) Ans=i-1,ans=temp; return i-1; } } } inline void dfs(int d) { int p=f(); for(rg int i=temp[(int)temp.size()-1]+1;i<=p+1;++i) { temp.push_back(i),f(); if(d<k) dfs(d+1); temp.pop_back(); } } int main() { scanf("%d%d",&n,&k);temp.push_back(1); dfs(2); for(rg int i=0;i<ans.size();++i) printf("%d ",ans[i]); printf("\nMAX=%d",Ans); return 0; }