标签:
下面是difficulty 1的题
1003 Max Sum
最长递增子序列。非常经典,最棒的解法是在线算法O(n)的复杂度。
贴的呢,是用dp做的代码。
先是一个高亮的dp递推式,然后找到最大处,用k记录。即所求的子序列的结尾,之后倒推,用减法推出子序列的开头位置。
要注意的点就是各个变量的初始化,初始化不好,很容易WA。还有找子序列的头的时候,倒推的时候找到等值的数是不跳出的,但是更新gx的值,因为0的存在。
1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4 int a[100005]; 5 int dp[100005]; 6 int main() 7 { 8 int t; 9 cin>>t; 10 int p=1; 11 while(t--) 12 { 13 int n; 14 cin>>n; 15 for(int i=1;i<=n;i++) 16 { 17 cin>>a[i]; 18 } 19 memset(dp,0,sizeof(dp)); 20 for(int i=1;i<=n;i++) 21 { 22 if(dp[i-1]<0) 23 dp[i]=a[i]; 24 else 25 dp[i]=dp[i-1]+a[i]; 26 } 27 28 int ans=dp[1],k=1; 29 for(int i=1;i<=n;i++) 30 { 31 if(dp[i]>ans) 32 { 33 ans=dp[i]; 34 k=i; 35 } 36 } 37 int max=ans; 38 int gx=k,sx=k; 39 for(int i=k;i>=1;i--) 40 { 41 max-=a[i]; 42 if(max==0) sx=i; 43 } 44 45 cout<<"Case "<<p++<<":"<<endl; 46 cout<<ans<<" "<<sx<<" "<<gx<<endl; 47 if(t!=0) cout<<endl; 48 } 49 return 0; 50 }
1025 Constructing Roads In JGShining‘s Kingdom
这道题也是非常非常经典的,重点是怎么去想到这是一个LIS。
你把一条轴上的看成数组的下标,一条轴上的看成数组的值,一一对应起来,发现它所要求的就是该数组中的LIS。
这里写的是nlogn的LIS的方法。具体的可以看看书或者网上的博客,LIS本来朴素的做法是n²的,但是当你换一个方式dp,dp[n]表示的是长度为n+1的子序列的结尾的最大值。就可以降到nlogn。
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 using namespace std; 5 const int maxn = 500000+50; 6 const int INF = 0x3f3f3f3f; 7 int road[maxn],dp[maxn]; 8 int main() 9 { 10 int n,x,y; 11 int p = 1; 12 while(~scanf("%d",&n)) 13 { 14 for(int i=0;i<n;i++) 15 dp[i] = INF; 16 for(int i=0;i<n;i++) 17 { 18 scanf("%d%d",&x,&y); 19 road[x] = y; 20 } 21 for(int i=1;i<=n;i++) 22 { 23 *lower_bound(dp,dp+n,road[i]) = road[i]; 24 } 25 int len = lower_bound(dp,dp+n,INF) - dp; 26 27 printf("Case %d:\n",p++); 28 printf("My king, at most %d road",len); 29 if(len!=1) printf("s"); 30 printf(" can be built.\n\n"); 31 } 32 return 0; 33 }
1058 Humble Numbers
这道题比较恶心的是输出,英文的序数词的格式orz。
这段dp也比较奇特,对当时的我来说。
1 int i=1,p2=1,p3=1,p5=1,p7=1; 2 rec[i++] = 1; 3 while(i<=5842) 4 { 5 int one = min(2*rec[p2],3*rec[p3]); 6 int two = min(5*rec[p5],7*rec[p7]); 7 rec[i] = min( one , two ); 8 if(rec[i] == 2*rec[p2]) p2++; 9 if(rec[i] == 3*rec[p3]) p3++; 10 if(rec[i] == 5*rec[p5]) p5++; 11 if(rec[i] == 7*rec[p7]) p7++; 12 i++; 13 }
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 5 int rec[6000]; 6 int main() 7 { 8 int i=1,p2=1,p3=1,p5=1,p7=1; 9 rec[i++] = 1; 10 while(i<=5842) 11 { 12 int one = min(2*rec[p2],3*rec[p3]); 13 int two = min(5*rec[p5],7*rec[p7]); 14 rec[i] = min( one , two ); 15 if(rec[i] == 2*rec[p2]) p2++; 16 if(rec[i] == 3*rec[p3]) p3++; 17 if(rec[i] == 5*rec[p5]) p5++; 18 if(rec[i] == 7*rec[p7]) p7++; 19 i++; 20 } 21 int n; 22 while(~scanf("%d",&n) && n) 23 { 24 if(n%10 == 1 && n%100 != 11) 25 printf("The %dst humble number is %d.\n",n,rec[n]); 26 else if(n%10 == 2 && n%100 != 12) 27 printf("The %dnd humble number is %d.\n",n,rec[n]); 28 else if(n%10 == 3 && n%100 != 13) 29 printf("The %drd humble number is %d.\n",n,rec[n]); 30 else 31 printf("The %dth humble number is %d.\n",n,rec[n]); 32 } 33 return 0; 34 }
1059 Dividing
hdu分类 Dynamic Programming(这是一场漫长的旅途)
标签:
原文地址:http://www.cnblogs.com/luosuo10/p/5721160.html