6-1 A - 递归的函数
#include <stdio.h>
int p[31][31][31];
int f(int a,int b,int c)
{
if(a<=0||b<=0||c<=0) return 1;//返回值为1的是单独的一个判断程序
if(p[a][b][c]>0) return p[a][b][c];//从这里开始,是返回值为函数值的判断程序,如果p[a][b][c]>0,意味着已经判断过一次,直接返回就行,不需要再判断了,这样就不会超时了
else if(a>20||b>20||c>20) return p[a][b][c]=f(20,20,20);
else if(a<b&&b<c) return p[a][b][c]=f(a,b,c-1)+f(a,b-1,c-1)-f(a,b-1,c);
else return p[a][b][c]=f(a-1,b,c)+f(a-1,b-1,c)+f(a-1,b,c-1)-f(a-1,b-1,c-1);
}
int main()
{
int a,b,c;
while(~scanf("%d %d %d",&a,&b,&c))
{
printf("%d\n",f(a,b,c));
}
return 0;
}
6-2 B - 数字三角形问题
#include <stdio.h>
int max(int a,int b)
{
return a>b?a:b;//判断大小函数,如果a>b,输出a,否则输出b
}
int a[101][101];
int ans[101][101];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
scanf("%d",&a[i][j]);
}
}
for(int i=1;i<=n;i++)
{
ans[n][i]=a[n][i];
}//将ans的最后一行赋值
for(int i=n-1;i>=1;i--)
{
for(int j=1; j<=i; j++)
{
ans[i][j]=max(ans[i+1][j],ans[i+1][j+1])+a[i][j];//只能向下或者向右下走,所以判断下或者右下哪个大就好
}
}
printf("%d\n",ans[1][1]);
return 0;
}
6-3 C - 小鑫去爬山
#include <stdio.h>
int min(int a,int b)//构造函数筛选最小值
{
return a<b?a:b;
}
int a[101][101];
int ans[101][101];
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=1; i<=n; i++)
{
for(int j=1; j<=i; j++)
{
scanf("%d",&a[i][j]);
}
}
for(int i=1; i<=n; i++)
{
ans[n][i]=a[n][i];//将第n行赋值,方便后面选择
}
for(int i=n-1; i>=1; i--)//相当于一行一行往上走
{
for(int j=1; j<=i; j++)
{
ans[i][j]=min(ans[i+1][j],ans[i+1][j+1])+a[i][j];//选择下一行的j和j+1列中较小的一个进行相加
}
}//与上题差不多
printf("%d\n",ans[1][1]);
}
return 0;
}
6-4 D - 最长公共子序列问题
#include <stdio.h>
#include <string.h>
int max(int a,int b)//构造max函数,筛选最大值
{
return a>b?a:b;
}
int main()
{
char s1[501],s2[501];
int n1,n2,a[501][501];
while(~scanf("%s %s",s1,s2))
{
n1=strlen(s1);
n2=strlen(s2);
for(int i=0;i<=n1;i++)
{
a[i][0]=0;
}
for(int i=0;i<=n2;i++)
{
a[0][i]=0;
}//以s1+1的长度为行,s2+1的长度位列,赋值矩阵 首行首列为0
for(int i=1;i<=n1;i++)
{
for(int j=1;j<=n2;j++)
{
if(s1[i-1]==s2[j-1])
{
a[i][j]=a[i-1][j-1]+1;
}
else
a[i][j]=max(a[i-1][j],a[i][j-1]);
}
}
printf("%d\n",a[n1][n2]);
}
return 0;
}
和上图差不多的,需要理解,不好讲;
6-5 E - 最长上升子序列
#include <stdio.h>
#include <string.h>
int max(int a,int b)//max函数,筛选最大值
{
return a>b?a:b;
}
int main()
{
int n,a[1001],b[1001];
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%d",&a[i]);
b[0]=1;//初始化边界条件,以a[0]结尾的最长上升子序列长度为1
}
for(int i=1;i<n;i++)//让i从1开始,计算以a[i]结尾的最长上升子序列长度
{
int Max=0;//j<i时最长上升子序列长度
for(int j=0;j<i;j++)
{
if(a[i]>a[j]&&b[j]>Max)//若a[j]<a[i]且Max小于以a[j]为结尾的最长上升子序列
Max=b[j];//则为Max赋新值
}
b[i]=Max+1;//则以b[i]结尾的最长上升子序列为以b[j]结尾的最长上升子序列+1
}
int ans=-1;
for(int i=0;i<n;i++)
{
ans=max(ans,b[i]);//筛选以b[i]结尾的最长上升子序列的长度的最大值
}
printf("%d",ans);
return 0;
}
6-6 F - 上升子序列
#include <stdio.h>
#include <string.h>
int max(int a,int b)
{
return a>b?a:b;
}
int main()
{
int n,a[1001],b[1001];
while(~scanf("%d",&n))
{
for(int i=0; i<n; i++)
{
scanf("%d",&a[i]);
}
b[0]=a[0];//以b[0]结尾的最大上升子序列和为a[0]
for(int i=1;i<n;i++)//下面和上题几乎一模一样,不做过多赘述
{
int Max=0;
for(int j=0;j<i;j++)
{
if(a[i]>a[j]&&b[j]>Max)
Max=b[j];
}
b[i]=Max+a[i];
}
int ans=-1;
for(int i=0; i<n; i++)
ans=max(ans,b[i]);
printf("%d\n",ans);
}
return 0;
}
6-7 G - 最长公共子序列
不懂,直接放学长大佬的
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char a[110][110];
int dp[30000 + 10];
int len[110];
int n;
int DP( int *x )//x记录每个字符串的动态长度,即每个状态对应的每个字符串长度,这里需要一定理解,每个状态可以想成把一部分字符串丢掉,即长度减少
{
int i, j, index, ret;
for( i = 1; i <= n; i++ )//如果有一个字符串的长度为0,那么最长公共子序列必定为0
{
if( x[i] == 0 )
{
return 0;
}
}
for( index = x[n] - 1, i = n - 1; i >= 1; i-- )
{
index = index * len[i] + x[i] - 1; //转化为一维数组,这里可以自己推导一下,上面分享的博客里有解释
}
if( dp[index] >= 0 )//如果之前求过这个状态直接返回,减少重复计算,dp的核心思想
{
return dp[index];
}
//从每个字符串的末尾开始匹配
for( i = 2; i <= n; i++ )
{
if( a[1][x[1] - 1] != a[i][x[i] - 1] )
{
break;
}
}
if( i > n )//如果都相等则把字符串长度都-1,答案就行-1后字符串求dp的答案+1
{
for( j = 1; j <= n; j++ )
{
x[j]--;
}
ret = DP(x) + 1;//dp求得长度-1的字符串状态的最长+1
for( j = 1; j <= n; j++ )
{
x[j]++;
}
}
else
{
ret = 0;
int t;
//开始枚举每一种情况,取最大值保留
for( j = 1; j <= n; j++ )
{
x[j]--;
t = DP( x );
ret = max( ret, t );
x[j]++;
}
}
dp[index] = ret;//记忆化
return ret;
}
int main()
{
int T;
int L[110];
scanf("%d", &T);
while( T-- )
{
scanf("%d", &n);
for( int i = 1; i <= n; i++ )
{
scanf("%s",a[i] );
len[i] = L[i] = strlen( a[i] );
}
memset( dp, -1, sizeof(dp) );
printf("%d\n", DP( L ) );
}
return 0;
}
6-8 H - 取数字问题
#include <stdio.h>
int max(int a,int b)
{
return a>b?a:b;
}
int n,m;
int ans=0x3f3f3f3f,a[11][11];//ans设为int范围的最大值,用于下面验证。
void dp(int i,int j,int sum)//i,j表示现在在哪个点,sum表示从原点到(i,j)的和
{
sum=sum+a[i][j];
if(i<m-1)//如果没到最下边,则继续往下走,i+1表示向下一行的意思
dp(i+1,j,sum);
if(j<n-1)//如果没到最右边,则继续向右走
dp(i,j+1,sum);
if(i==m-1&&j==n-1&&sum>0&&sum<ans)//到达右下角了,判断这条路是否满足正数最小
ans=sum;
}
int main()
{
scanf("%d %d",&m,&n);
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
scanf("%d",&a[i][j]);
}
}
dp(0,0,0);//从原点开始
if(ans==0x3f3f3f3f)//如果ans值不变,意味着不能得到正整数
printf("-1");
else
printf("%d",ans);
return 0;
}
6-9 I - 免费馅饼
#include<stdio.h>
#include<string.h>
int max(int a,int b)
{
return a>b?a:b;
}
int dp[100001][15];
int main()
{
int n;
while(~scanf("%d",&n)&&n!=0)
{
int t1=0;
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++)
{
int x,t;
scanf("%d %d",&x,&t);
t1=max(t1,t);
dp[t][x]++;
}
for(int i=t1-1;i>=0; i--)
{
dp[i][0]=dp[i][0]+max(dp[i+1][0],dp[i+1][1]);
for(int j=1;j<=10;j++)
{
dp[i][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;
}
6-10 J - 走迷宫
不怎么明白就不乱解释了,放学长大佬代码
#include<stdio.h>
#include<string.h>
struct node
{
int x, y;
} ls[1000];
int dx[] = {0,-1,0,1}, dy[] = {-1,0,1,0};
int bj[16][16], map[16][16];
int m, n, step, sum = 0, xz, yz;
void dfs(int x1, int y1)
{
int i;
if(x1 == xz && y1 == yz)
{
sum++;
for(i = 0; i < step; i++)
{
printf("(%d,%d)",ls[i].x,ls[i].y);
if(i < step - 1)
printf("->");
}
printf("\n");
}
else
{
int kx, ky;
for(i = 0; i < 4; i++)
{
kx = x1 + dx[i];
ky = y1 + dy[i];
if(kx >= 1 && ky >= 1 && kx <= n && ky <= m && !bj[kx][ky] && map[kx][ky])
{
ls[step].x = kx;
ls[step].y = ky;
step++;
bj[kx][ky] = 1;
dfs(kx,ky);
bj[kx][ky] = 0;
step--;
}
}
}
}
int main()
{
int i, j,xq,yq;
while(~scanf("%d%d",&n,&m))
{
memset(bj,0,sizeof(bj));
memset(ls,0,sizeof(ls));
for(i = 1; i <= n; i++)
for(j = 1; j <= m; j++)
scanf("%d",&map[i][j]);
scanf("%d%d%d%d",&xq,&yq,&xz,&yz);
ls[0].x = xq;
ls[0].y = yq;
sum = 0;
step = 1;
bj[xq][yq] = 1;
dfs(xq,yq);
if(sum == 0)
printf("-1\n");
}
return 0;
}
加油加油加油!!!