标签:main res mic close 合并 org turn size microsoft
知识储备:dp入门。
好了,完成了dp入门,我们可以做一些稍微不是那么裸的题了。
------------------------------------------------------------------------------------
分析:曾经的noi系列。石子合并问题分好几种情况。
这题是环形的,且只能合并相邻的两堆,那么我们把石子数组展开,如[1,2,3,4,5] -> [1,2,3,4,5,1,2,3,4,5],这样进行处理,就能将环形转换成直线。
转换完之后,就可以用dp做了,dp的解释详见代码。这题数据过得去,时间是 O(n3) 不然要用平行四边形优化。
安利一发acdreamer的博客,把石子合并问题讲的很清楚http://blog.csdn.net/acdreamers/article/details/18039073
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 int sum[205],mins[205][205],maxs[205][205],s[205][205];//dp[i][j]=i~j的最大得分 5 int main() 6 { 7 int a,n,minnum=9999999,maxnum=-minnum; 8 scanf("%d",&n); 9 for(int i=1;i<=n;i++) 10 { 11 scanf("%d",&sum[i]); 12 sum[i+n]=sum[i]; 13 s[i][i]=i; 14 s[i*2][i*2]=i; 15 } 16 for(int i=1;i<=2*n;i++) sum[i]+=sum[i-1]; //前缀和 17 for(int l=1;l<=n;l++)//区间长度 18 { 19 for(int i=1;i+l<=2*n;i++)//开始的端点 20 { 21 22 int j=i+l;//结束的端点 23 maxs[i][j]=-99999999;mins[i][j]=-1*maxs[i][j]; 24 for(int k=i;k<j;k++) 25 { 26 maxs[i][j]=max(maxs[i][j],maxs[i][k]+maxs[k+1][j]+sum[j]-sum[i-1]); 27 mins[i][j]=min(mins[i][j],mins[i][k]+mins[k+1][j]+sum[j]-sum[i-1]); 28 } 29 } 30 } 31 for(int i=1;i<=n;i++)//因为是环形的,可从任意两堆间分开,所以需要枚举一遍起点从1~n 32 { 33 maxnum=max(maxs[i][i+n-1],maxnum); 34 minnum=min(mins[i][i+n-1],minnum); 35 } 36 printf("%d\n%d",minnum,maxnum); 37 return 0; 38 }
分析:第一问还是很简单的,求最长下降子序列。第二问要计算方案数量,还要判重。
用t[i]表示前i个股票的不同方案个数,可以得出,如果存在dp[j]==dp[i] && a[j]==a[i]方案就是重复的,所以就把t[i]赋为0,如果f[i]==f[j]+1,那么i可以从j转移,所以t[i]+=t[j]。最后统计和即可。
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 int dp[5005],a[5005],t[5005];//t,计算出现次数的dp 5 int main() 6 { 7 int ans=-99999,n,k=0,res=0; 8 scanf("%d",&n); 9 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 10 for(int i=1;i<=n;i++) 11 { 12 dp[i]=1; 13 for(int j=1;j<i;j++) 14 { 15 if(a[j]>a[i]) dp[i]=max(dp[i],dp[j]+1); 16 } 17 ans=max(ans,dp[i]); 18 } 19 for(int i=1;i<=n;i++) 20 { 21 if(dp[i]==1) t[i]=1;//如果无法转移则为1 22 for(int j=1;j<i;j++) 23 { 24 if(dp[j]==dp[i]-1 && a[i]<a[j])//判前继 判可以为下一个数 25 { 26 t[i]+=t[j];//转移 27 } 28 else if(dp[i]==dp[j]&&a[i]==a[j]) t[j]=0;//判重 29 } 30 } 31 for(int i=1;i<=n;i++) 32 { 33 if(dp[i]==ans) res+=t[i]; 34 } 35 printf("%d %d",ans,res); 36 return 0; 37 }
标签:main res mic close 合并 org turn size microsoft
原文地址:http://www.cnblogs.com/noblex/p/7627129.html