ACM Steps_Chapter Three_Section2

Max Sum

#include<iostream>
using namespace std;
int a[100001];
int main()
{
	int T;
	int i,n,position1,end,thissum,maxsum,begin;
	cin>>T;
	for(int tt=1;tt<=T;tt++)
	{
		cin>>n;
		for(i=0;i<n;i++)
			scanf("%d",&a[i]);
		position1=begin=end=0;
		maxsum=thissum=a[0];
		for(i=1;i<n;i++)
		{
			if(thissum+a[i]<a[i])//如果当前值比a[i]小的话则改为a[i]  
			{
				thissum=a[i];
				position1=i;	//记录下改的位置  
			}
			else
			{
				thissum=thissum+a[i];
			}
			if(thissum>maxsum)	//当前值比最大值大,则头尾都要改
			{
				maxsum=thissum;
				begin=position1;
				end=i;
			}
		}
		printf("Case %d:\n%d %d %d\n",tt,maxsum,begin+1,end+1); 
		if(tt!=T)
		{
			cout<<endl;
		}
	}
	system("pause");
	return 0;
}

Common Subsequence

#include<iostream>
#include<cstring>
using namespace std;
char str1[1001];
char str2[1001];
int dp[1001][1001];
int main()
{
	int i,j,max,len1,len2;
	while(cin>>str1>>str2)
	{
		len1=strlen(str1);
		len2=strlen(str2);
		for(i=0;i<len1;i++)
		{
			dp[i][0]=0;
		}
		for(i=0;i<len2;i++)
		{
			dp[0][i]=0;
		}
		for(i=1;i<=len1;i++)
		{
			for(j=1;j<=len2;j++)
			{
				if(str1[i-1]==str2[j-1])
				{
					dp[i][j]=dp[i-1][j-1]+1;
				}
				else
				{
					dp[i][j]=dp[i-1][j]>dp[i][j-1]?dp[i-1][j]:dp[i][j-1];
				}
			}
		}
		cout<<dp[len1][len2]<<endl;
	}
	system("pause");
	return 0;
}
	

FatMouse's Speed

/*
首先按照关键字W升序进行排序,然后S[i]从1到i-1(是指外层循环中的第i个元素)开始遍历,
找到w[i]>w[k],s[i]<s[k],使m[i]最大的位置,并记录。
动态规划状态方程为:f[i] = max(f[k]+1,f[i]),1<=k<i;
这里定义了一个struct mice 其中的len代表当前元素的状态长度,用来找到找到最长的,
index用来记忆当前元素的真实下标,在排序后还能找到元素的下标。
before用来找的当前元素的上一个元素的下标。
*/
#include <iostream>
#include <stdlib.h>
using namespace std;
typedef struct
{
    int w,s;
    int len,index;
    int before;
}mice;
int cmp(const void *a,const void *b)
{
    mice c = *(mice *)a;
    mice d = *(mice *)b;
    if(c.w==d.w)
    return d.s - c.s;
    else return c.w - d.w;
}
int main()
{
    mice m[10001];
    int i = 1,flag,max=0,f[1001];
    while(cin>>m[i].w>>m[i].s)
    {
        m[i].index = i;
        m[i].len=0;
        m[i].before=0;
        i++;
    }
    //cout<<i<<endl;
    qsort(m,i-1,sizeof(m[1]),cmp);
    for(int j = 1;j < i ;j++)
    {
        for(int k = 1; k< j;k++)
        {
            if(m[j].w>m[k].w&&m[j].s<m[k].s)
            {
                if(m[j].len<m[k].len+1)
                {
                    m[j].len = m[k].len+1;
                    m[j].before = k;
                    if(m[j].len>=max)
                    {
                        max = m[j].len;
                        flag = j;
                    }
                }


            }
        }
    }
    cout<<max+1<<endl;
    f[1] = m[flag].index;
    i=2;
     while(m[flag].before!=0)
    {
        flag = m[flag].before;
        f[i] = m[flag].index;
        i++;
    }
    for(int j = i-1 ; j >=1 ; j--)
    {
        cout<<f[j]<<endl;
    }
   // for(int j = 1 ; j < i ;j++)
   // cout<<m[j].index<<" "<<m[j].w<<" "<<m[j].s<<endl;
    return 0;
}

Humble Numbers

/*
分析:用dp的思维解答

 若一个数是Humble数,那么他的2、3、5、7倍仍然是Humble数。

 定义a为第i个Humble数

 a[n] = min( 2*a[m],3*a[n],5*a[k],7*a[l] ),m,n,k,l在被选择后彼此移动。
 */
#include <iostream>
using namespace std;
int main()
{
    int a[5843]={1},i,j,k,l,m,n,x[4],min;
    m = n = k = l = 1;
    for(i = 1;i < 5843;i++)
    {
          x[0]=a[m-1]*2;
          x[1]=a[n-1]*3;
          x[2]=a[k-1]*5;
          x[3]=a[l-1]*7;
          min = x[0];
          if (x[1] < min)
             min = x[1];
          if (x[2] < min)
             min = x[2];
          if (x[3] < min)
             min = x[3];
          a[i] = min;
          if(min == x[0])
             m++;
          if(min == x[1])
             n++;
          if(min == x[2])
             k++;
          if(min == x[3])
             l++;
    }
    while(cin >> n,n)
    {
          if(n % 10 == 1 && n % 100 != 11)
               printf("The %dst humble number is %d.\n",n,a[n-1]);
          else if(n % 10 == 2 && n % 100 != 12)
               printf("The %dnd humble number is %d.\n",n,a[n-1]);
          else if(n % 10 == 3 && n % 100 != 13)
               printf("The %drd humble number is %d.\n",n,a[n-1]);
          else
               printf("The %dth humble number is %d.\n",n,a[n-1]);
    }
    return 0;
}

Monkey and Banana

/*
类似于最长上升子序列,把箱子拆成3*n个,这样相当于把一个箱子分成高度不同的3个,
按底面积从小到大排好,根据转移方程dp[i]=max{dp[j]}+c[i](1<=j<i&&a[i]>a[j]&&b[i]>b[j]),
其中dp[i]表示前i个箱子能堆起的最大高度。
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct R
{
	int a;
	int b;
	int c;
	int s;
}r[200];
bool cmp(R a,R b)
{
	return a.s<b.s;
}
int main()
{
	int m=1,n,i,j,k,l,w,h,dp[200],temp,ans;
	while(scanf("%d",&n)!=-1&&n)
	{
		ans=0;
		memset(dp,0,sizeof(dp));
		k=1;
		for(i=1;i<=n;i++)
		{
			scanf("%d%d%d",&l,&w,&h);
			r[k].a=l;r[k].b=w;r[k].c=h;r[k].s=r[k].a*r[k].b;
			k++;
			r[k].a=w;r[k].b=l;r[k].c=h;r[k].s=r[k].a*r[k].b;
			k++;
			r[k].a=h;r[k].b=l;r[k].c=w;r[k].s=r[k].a*r[k].b;
			k++;
			r[k].a=h;r[k].b=w;r[k].c=l;r[k].s=r[k].a*r[k].b;
			k++;
			r[k].a=l;r[k].b=h;r[k].c=w;r[k].s=r[k].a*r[k].b;
			k++;
			r[k].a=w;r[k].b=h;r[k].c=l;r[k].s=r[k].a*r[k].b;
			k++;
		}
		sort(r+1,r+k,cmp);
		dp[1]=r[1].c;
		for(i=1;i<k;i++)
		{
			temp=0;
			for(j=1;j<i;j++)
				if(r[i].a>r[j].a&&r[i].b>r[j].b&&temp<dp[j])
					temp=dp[j];
			dp[i]=temp+r[i].c;
		}
		for(i=1;i<k;i++)
			if(ans<dp[i])
				ans=dp[i];
		printf("Case %d: maximum height = %d\n",m++,ans);
	}
	return 0;
}

数塔

/*
此题采用动态规划自底向上计算,如果我们要知道所走之和最大,
那么最后一步肯定是走最后一排数其中一个,向上退,
倒数第二步肯定走最后一排数对应的倒数第二排最大的一个
(将最后对应最后步走的最大的数加起来存在倒数第二步的数组中)再向上推,
一直推到最上面的第0布,那么b[0][0]最后所存的结果一定是最大的
*/

#include<iostream>
using namespace std;
int main()
{
	int T;
	int a[101][101];
	int dp[101][101];
	cin>>T;
	while(T--)
	{
		int n;
		cin>>n;
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<=i;j++)
			{
				cin>>a[i][j];
			}
		}
		dp[0][0]=0;
		for(int i=n-1;i>=0;i--)
		{
			for(int j=i;j>=0;j--)
			{
				if(i==n-1)
				{
					dp[i][j]=a[i][j];
				}
				else
				{
					dp[i][j]=max(a[i][j]+dp[i+1][j],a[i][j]+dp[i+1][j+1]);
				}
			}
		}
		cout<<dp[0][0]<<endl;
	}
	system("pause");
	return 0;
}

免费馅饼

#include<stdio.h>
#include<cmath>
#include<algorithm>
using namespace std;
int dp[100005][12];
int main()
{
    int n,i,j,maxt;
    int x,t;
    while(scanf("%d",&n),n)
    {
        maxt=0;
        memset(dp,0,sizeof(dp));
        for(i=0;i<n;i++)
        {
            scanf("%d%d",&x,&t);
            dp[t][x]++;
            if(maxt<t)  
				maxt=t;
        }
        for(i=maxt-1;i>=0;i--)
        {
            dp[i][0]+=max(dp[i+1][1],dp[i+1][0]);
            for(j=1;j<11;j++)
            {
                dp[i][j]+=max(max(dp[i+1][j-1],dp[i+1][j]),dp[i+1][j+1]);
            }   
        }
        printf("%d\n",dp[0][5]);     
    }
    return 0;  
}

命运

/*
设f[i][j]为走到(i,j)位置得到的最大权值。
则f[i][j] = max {f[i-1][j],f[i][j-1],f[i][j*k](2<k <m/j)}+a[i][j]。
再把f[i][j]初始化成-inf.f[1][1] =a[0][0].
*/
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

int main()
{
    int c,n,m,a[21][1010],dp[21][1010],max;
    cin>>c;
    while(c--)
    {
        cin>>n>>m;
        memset(dp,0,sizeof(dp));
       // max = -101
        for(int i = 1 ; i <= n ; i++)
        {
            for(int j = 1 ; j <= m ; j++)
            {
               // cin>>a[i][j];
               scanf("%d",&a[i][j]);
                dp[i][j] = a[i][j];
                if(i == 1) 
					max = -101;//注意:有出现全负,所以第一行应设为小于最小值。
                else 
					max = dp[i-1][j];
                for(int k = 1 ; k <= j/2;k++)
                {
                    if(j%k==0)
                    	if(max<dp[i][k])
                    		max = dp[i][k];
                }
                if(max < dp[i][j-1])
                	max = dp[i][j-1];
                dp[i][j] += max;
            }
        }
        cout<<dp[n][m]<<endl;
    }
    return 0;
}


posted @ 2013-04-22 15:52  VeryBigMan  阅读(125)  评论(0编辑  收藏  举报