#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;
}