C/C++入门练习题(25-27)

8 篇文章 3 订阅

25.数字三角形

题目描述

有一个由数字组成的三角形数塔,站在上一层的某个点,只能到达其下方左右的两个点。现在请找到一条从上到下的路径,使得路径上所有数字相加之和最大

4274F9B8E6E14581A4EC851BCE349029.jpg


输入

第一行输入一个数字 n(1≤n≤1000)(1≤n≤1000)代表数塔层数

接下来n行,按数塔图形,每行有一个或多个的整数,表示该层节点的值(节点值≤100000)(节点值≤100000)

输出

输出一个整数,代表从上到下路径上所有数字相加和的最大值。

样例输入1

6
3
9 5
4 2 1
3 4 9 6
3 5 3 7 3
2 1 3 9 3 2

样例输出1

39

数据规模与约定

时间限制:1 s

内存限制:64 M

100% 的数据保证 1≤n≤1000

题解思路

* 本题是经典的动态规划问题:
* 状态:d[i][j]表示从(i,j)出发,能得到的最大和。包括(i,j)
* 那么原问题便转化成了求d[0][0]
* 从(i,j)出发可以向下走(i+1,j),也可以向右下走(i+1,j+1),
* 然后问题就变成了从(i+1,j)或者从(i+1,j+1)出发的最大和
* 于是状态转移方程为:d[i][j] = max(d[i+1][j], d[i+1][j+1]) + a[i][j]

完整代码:
/*************************************************************************
	> File Name: 1.triangle.cpp
	> Author: 数字三角形
	> Mail: 
	> Created Time: 2021年02月20日 星期六 09时03分01秒
 ************************************************************************/
#include<iostream>
#include<cstdio>
using namespace std;
 
#define MAX_NUM 100
int d[MAX_NUM + 10][MAX_NUM + 10];
int N;
 
int MaxSum(int r,int j)  //递归求解最大路径和 
{
	if(r == N)
		return d[r][j];
	int sum1 = MaxSum(r + 1, j);
	int sum2 = MaxSum(r + 1, j + 1);
	if(sum1 > sum2)
		return sum1 + d[r][j];
	return sum2 + d[r][j];
}
 
int main()
{
	int m;
	cin >> N;
	for(int i = 1; i <= N; i++)
		for(int j = 1; j <= i; j++)
			cin >> d[i][j];
	cout << MaxSum(1,1);
	return 0;
}

26.钓鱼(贪心)

题目描述

有N个鱼塘排成一排(N<100),每个鱼塘中有一定数量的鱼,例如:N=5时,如下表:

鱼塘编号每1分钟能钓到的鱼的数量(1…1000)每1分钟能钓鱼数的减少量(1…100)当前鱼塘到下一个相邻鱼塘需要的时间(单位:分钟)11023214453206441654593鱼塘编号12345每1分钟能钓到的鱼的数量(1…1000)101420169每1分钟能钓鱼数的减少量(1…100)24653当前鱼塘到下一个相邻鱼塘需要的时间(单位:分钟)3544

即:在第1个鱼塘中钓鱼第1分钟内可钓到10条鱼,第2分钟内只能钓到8条鱼,……,第5分钟以后再也钓不到鱼了。从第1个鱼塘到第2个鱼塘需要3分钟,从第2个鱼塘到第3个鱼塘需要5分钟,……

给出一个截止时间T(T<1000),设计一个钓鱼方案,从第1个鱼塘出发,希望能钓到最多的鱼。

假设能钓到鱼的数量仅和已钓鱼的次数有关,且每次钓鱼的时间都是整数分钟。

【输入】

共5行,分别表示:

第1行为N;

第2行为第1分钟各个鱼塘能钓到的鱼的数量,每个数据之间用一空格隔开;

第3行为每过1分钟各个鱼塘钓鱼数的减少量,每个数据之间用一空格隔开;

第4行为当前鱼塘到下一个相邻鱼塘需要的时间;

第5行为截止时间T。

【输出】

一个整数(不超过231−1231−1),表示你的方案能钓到的最多的鱼。

【输入样例】

5
10 14 20 16 9
2 4 6 5 3
3 5 4 4
14

【输出样例】

76
解题思想

问题抽取

  • 变量太多了,行走时间,停留时间
  • 湖比较少,我们枚举最后停留的湖,把行走时间变成常量
  • 问题中以5分钟作为基本单位,不妨把5去掉
  • 行走时间为常量,那问题等价为佳佳可以瞬间移动

解题思路:用堆和贪心的方法,先把各项数据读入并存储在数组里面,然后开始枚举最远走到的池塘编号,收集能够钓鱼的池塘的资料,接着把堆初始化,并用贪心选取鱼最多的池塘,最后输出最优解即可。

完整代码:
/*************************************************************************
	> File Name: 2.fishing.cpp
	> Author: 钓鱼(贪心)
	> Mail: 
	> Created Time: 2021年02月20日 星期六 14时12分01秒
 ************************************************************************/

#include<iostream>
#include<stdio.h>
using namespace std;
int a[105],b[105],c[105],v[105];
int main()
{  freopen("fishing.in","r",stdin);
   freopen("fishing.out","w",stdout);
   int n;
   cin>>n;
   for (int i=1;i<=n;++i)
   {  cin>>a[i];
   }
   for (int i=1;i<=n;++i)
   cin>>b[i];
   for (int i=1;i<=n-1;++i)
   {  cin>>c[i];
      c[i]=c[i]+c[i-1];
        }
   int maxxx=0;
   int t;cin>>t;
   for (int i=1;i<=n;++i)
   {  int s=t;
      s=s-c[i-1];
      int ans=0;
      for (int j=1;j<=i;++j)
        v[j]=a[j]+b[j];
      for (int j=1;j<=s;++j)
     {  int maxx=0,xh,y;
        for (int k=1;k<=i;++k)
        {  y=v[k]-b[k];
           if (y>maxx)
          { maxx=y;
            xh=k;
          }
        }
        v[xh]=v[xh]-b[xh];
        ans+=maxx;
     }
     maxxx=max(maxxx,ans);
   }
   cout<<maxxx;
}

27.墙壁涂色

题目描述

给一个环形的墙壁涂颜色,颜色一共有 k 种,墙壁被竖直地划分成 n 个部分,相邻的部分颜色不能相同。请你写程序计算出一共有多少种给墙壁上色的方案?

例如,当 n=5,k=3n=5,k=3 时,下面是一种合法的涂色方案

44934979.jpg

而由于墙壁是环形的,所以下面就是一种非法的方案

10258141.jpg

输入
输入两个数字 n,k(1≤n≤103,2≤k≤10)(1≤n≤103,2≤k≤10),分别代表墙壁数量和颜色种类。

输出
对于每个询问,输出一行整数,合法的墙壁涂色方案数。

样例输入1
5 3
样例输出1
30
数据规模与约定
时间限制:5 s

内存限制:256 M

20% 的数据保证 n≤20,k=3n≤20,k=3
40% 的数据保证 n≤40,k=4n≤40,k=4
80% 的数据保证 n≤40,k≤10n≤40,k≤10
100% 的数据保证 n≤103,k≤10n≤103,k≤10
递推高精度从递推到动归(一)提高组

题目分析

1.假设函数:设f[n]为n个尺寸的墙有几种不同排序

2.递推的本质:用已知推未知:寻找前后项之间的关系,仔细思考n-1和n之间的关系,可以分为两种情况

当第1项和第n-1项不同色时。第n项只有一种颜色可以取,即f[n]=f[n-1]

当第1项和第n-1项同色时。第n项有两种颜色可以取,同时因为第n块和第n-1块不同色,所以f[n]=2*f[n-2]

由高中数学知识,分类相加,不难得到f[n] = f[n-1] + f[n-2]*2 (n>3)

别忘了f[1]=3,f[2]=f[3]=6

完整代码:
/*************************************************************************
	> File Name: 3.tintage.cpp
	> Author: 墙壁涂色
	> Mail: 
	> Created Time: 2021年02月20日 星期六 23时05分01秒
 ************************************************************************/
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
 
const int maxn = 1000;
 
struct bign{
    int d[maxn], len;
 
	void clean() { while( len  > 1 && !d[len - 1]) len--; }
 
    bign() { 
        memset(d,  0,  sizeof(d));  len  =  1; 
    }
    bign(int num) 	{ *this  =  num; } 
	bign(char* num) { *this  =  num; }
    bign operator  =  (const char* num){
        memset(d,  0,  sizeof(d));  
        len = strlen(num);
        for(int i  =  0;  i  <  len;  i++) d[i]  =  num[len - 1 - i]  -  '0';
        clean();
		return *this;
    }
    bign operator = (int num){
        char s[20]; sprintf(s, "%d", num);
        *this  =  s;
		return *this;
    }
 
    bign operator  +  (const bign& b){
        bign c  =  *this; int i;
        for (i  =  0;  i  <  b.len;  i++){
        	c.d[i]  +=   b.d[i];
        	if (c.d[i]  >  9) c.d[i] %= 10,  c.d[i + 1]++;
		}
		while (c.d[i]  >  9) c.d[i++] %= 10,  c.d[i]++;
		c.len  =  max(len,  b.len);
		if (c.d[i] && c.len  <=  i) c.len  =  i + 1;
        return c;
    }
    bign operator - (const bign& b){
        bign c = *this; int i;
        for (i  =  0;  i < b.len; i++){
        	c.d[i] -= b.d[i];
        	if (c.d[i] < 0) c.d[i]+=10, c.d[i+1]--;
		}
		while (c.d[i] < 0) c.d[i++]+=10, c.d[i]--;
		c.clean();
		return c;
    }
    bign operator * (const bign& b)const{
        int i, j; bign c; c.len = len + b.len; 
        for(j = 0; j < b.len; j++) for(i = 0; i < len; i++) 
			c.d[i+j] += d[i] * b.d[j];
        for(i = 0; i < c.len-1; i++)
            c.d[i+1] += c.d[i]/10, c.d[i] %= 10;
        c.clean();
		return c;
    }
    bign operator / (const bign& b){
    	int i, j;
		bign c = *this, a = 0;
    	for (i = len - 1; i >= 0; i--)
    	{
    		a = a*10 + d[i];
    		for (j = 0; j < 10; j++) if (a < b*(j+1)) break;
    		c.d[i] = j;
    		a = a - b*j;
    	}
    	c.clean();
    	return c;
    }
    bign operator % (const bign& b){
    	int i, j;
		bign a = 0;
    	for (i = len - 1; i >= 0; i--)
    	{
    		a = a*10 + d[i];
    		for (j = 0; j < 10; j++) if (a < b*(j+1)) break;
    		a = a - b*j;
    	}
    	return a;
    }
	bign operator += (const bign& b){
        *this = *this + b;
        return *this;
    }
 
    bool operator <(const bign& b) const{
        if(len != b.len) return len < b.len;
        for(int i = len - 1; i >= 0; i--)
            if(d[i] != b.d[i]) return d[i] < b.d[i];
        return false;
    }
    bool operator >(const bign& b) const{return b < *this;}
    bool operator<=(const bign& b) const{return !(b < *this);}
    bool operator>=(const bign& b) const{return !(*this < b);}
    bool operator!=(const bign& b) const{return b < *this || *this < b;}
    bool operator==(const bign& b) const{return !(b < *this) && !(b > *this);}
 
    string str() const{
        char s[maxn] = {};
        for(int i = 0; i < len; i++) s[len - 1 - i]  =  d[i] + '0';
        return s;
    }
};
 
istream& operator >> (istream& in, bign& x)
{
    string s;
    in >> s;
    x = s.c_str();
    return in;
}
 
ostream& operator << (ostream& out, const bign& x)
{
    out <<  x.str();
    return out;
}
int main()
{
	bign ans;
	ans = 1;
	int n, m; cin >> n >> m;
	bign nn,mm;
	nn = n;
	mm = m;
	if(n % 2 == 0){
		for(int i = 1; i <= n; i++)
		ans = ans * (mm - 1);
		ans = ans + mm - 1;
		
	}
	else{
		for(int i = 1; i <= n; i++)
		ans = ans * (mm - 1);
		ans = ans - mm + 1;
	}
	cout <<  ans << endl;
	return 0;
}


  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值