个人训练总结

题目 1257: 超级楼梯
时间限制: 1s 内存限制: 128MB 提交: 1274 解决: 910
题目描述
有一楼梯共M级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第M级,共有多少种走法?

输入格式
输入数据首先包含一个整数N,表示测试实例的个数,然后是N行数据,每行包含一个整数M(1<=M<=40),表示楼梯的级数。

输出格式
对于每个测试实例,请输出不同走法的数量

样例输入
2
2
3
样例输出
1
2
个人思路:
一开始想复杂了,想着用递归解答,然后再加方案,最后发现局部变量没处理好,导致做不出来。
后来又想着都是1和2,直接连续的1组成2,这样更简单。方案也可以计算出来。
就是要注意,因为一开始落在第一级台阶,所以第一个1和第二个1是没办法组成2的,所以最后要+1;

#include<iostream>
using namespace std;
int main()
{
	int n;
	cin>>n;
	int a[n+1];
	for(int i=1;i<=n;i++)
	cin>>a[i];
	for(int i=1;i<=n;i++)
	{
		int ans=0;
		//纯1方案 
		ans++; 
		//上2层的方案
		ans=ans+a[i]-1;
		//因为在第一级楼梯,所以要减掉一种带2方案 
		ans--;
		cout<<ans<<endl; 
	} 
	return  0;
}
优化一下可以更简洁:
#include<iostream>
using namespace std;
int main() {
	int n;
	cin >> n;
	int a[n + 1];
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		int ans = 0;
		ans = ans + a[i] - 1;
		cout << ans << endl;
	}
	return  0;



}

题目 1233: 核电站问题
时间限制: 1s 内存限制: 128MB 提交: 458 解决: 306
题目描述
一个核电站有N个放核物质的坑,坑排列在一条直线上。如果连续3个坑中放入核物质,则会发生爆炸,于是,在某些坑中可能不放核物质。现在,请你计算:对于给定的N,求不发生爆炸的放置核物质的方案总数。

输入格式
输入文件只有多行,每行对应一个正整数N<=40;

输出格式
输出文件有多行,每行只有一个正整数,表示方案总数

样例输入
1
2
3
4
10
样例输出
2
4
7
13
504
个人思路:
利用递归进行赋值,1代表已经存放,0代表未存放,然后每次存放到最后一个的时候就进行条件检查,符合条件就给答案加上1,最后再输出,然后每次输入更新答案。
需要注意的点,这个跟排列有一个相似点,就是赋值要赋值到n位,那么递归就要递归到n+1位,因为到n+1位说明1~n位全部赋值完成,如果只是单纯的到n位那位最后会因为n位没有赋值导致答案错误

#include<iostream>
using namespace std;
int n;
int a[50];
long long ans=0; 
bool check()
{
  //检查此时的1-n号坑位是否满足不连续三爆条件
   for(int i=1;i<=n;i++)
   {
   	if(a[i]!=0)
   	{
	 //当前坑位已经存放了核物质,检查关于i号位的连续三位是否存放
//这里没有考虑左右连续三位,而考虑自左向右的连续三位是因为向右边检查过去,那边检查的i位的时候左边不会出问题
	 if(a[i+1]==1&&a[i+2]==1) return 0; 
	}	
   }
   return 1;	
}
void Assignment(int x,int y)
{
	if(x==y)  {if(check()) ans++;}
	else
	{ 
	//利用数组来存放
	//0代表未放,1代表已放
	for(int i=0;i<=1;i++)
	{
		a[x]=i;
		Assignment(x+1,y);
	}
	}
}
int main()
{
	//n代表n个放核物质的坑 
	while(cin>>n)
	{
		ans=0;
	    Assignment(1,n+1);
		cout<<ans<<endl; 	
	}
}

题目描述
从X星截获一份电码,是一些数字,如下:
13
1113
3113
132113
1113122113
....

YY博士经彻夜研究,发现了规律:
第一行的数字随便是什么,以后每一行都是对上一行“读出来”
比如第2行,是对第1行的描述,意思是:1个1,1个3,所以是:1113
第3行,意思是:3个1,1个3,所以是:3113

请你编写一个程序,可以从初始数字开始,连续进行这样的变换。
输入
第一行输入一个数字组成的串,不超过100位
第二行,一个数字n,表示需要你连续变换多少次,n不超过20

输出一个串,表示最后一次变换完的结果。
输出
输出一个串,表示最后一次变换完的结果。


样例输入
5
7
样例输出
13211321322115
个人思路:
通过双指针来运行,然后重复的时候就重复数字数量++,然后标记当前遍历的字母,如果外层循环下个左指针字母还是这个就跳过,内层循环结束后,把重复数量和相对应的字母赋值给ans,下标对应+2,更新重复数字数量。
当两个循环都结束后,要更新数组下标t=0,因为下一次的更新ans要从下标为0开始更新。并且要更新重复字母,防止上一次的最后一个字母刚好是这次第一个字母,那就会导致答案错误。
过程中遇到的问题:忘记每次change更新重复字母,导致在某一次更新中上一次的最后一个字母刚好是这次第一个字母导致答案错误。
AC代码:

#include<bits/stdc++.h>
using namespace std;
string s;
char ans[1000000]; 
int main()
{
	 //变换此数 
	int changenum;
	cin>>s>>changenum;
	//重复的字母 
	char cf='!';
	//cfnum是重复字母的个数,t是用于给答案数组赋值的下标 
	int cfnum=0,t=0;
	while(changenum--)
	{
	for(int i=0;i<s.size();i++)
	{
		//如果是之前遍历过的重复字母就跳过,比如aaa,遇到第2或3就跳过 
	if(s[i]==cf) continue;
	for(int j=i;j<s.size();j++)
	{
		//赋值新字母 
		cf=s[i];
		//重复就cfnum++ 
	    if(s[i]==s[j]) cfnum++;
	    //否则停止本层循环,进入下一个新字母 
	    else  break;
	}
	//将整型的cfnum转化为字符型输入进答案数组 
	ans[t]=cfnum+'0';
	//将此字母赋值进答案数组 
	ans[t+1]=cf;
	//在执行同一个s串的时候t每次+2 
	t+=2;
	//更新字母重复此数 
	cfnum=0;
	}
//	cout<<"s="<<s<<endl;
//	cout<<"ans="<<ans<<endl;
	
	//对于不同串的变换,需要每次都从下标为0的时候开始重新赋值新的答案ans 
	t=0;
	//将下次需要变换的s串更新为当前的ans 
	s=ans;
	//cout<<"s="<<s<<endl;
	//cout<<endl;
	//更新重复字母,防止下一个串的第一个字母上 
	cf='!';
	}
    //输出答案
	cout<<ans;
	return 0;
	
	
	
} 

碰碰车
难度:钻石时间限制:1秒占用内存:128M
游乐园玩碰碰车,其中有一种碰碰车是在一条直线上行驶。该碰碰车有一个初始朝向和初始位置,并且以每秒一个单位的速度向初始方向前行,当它和其它碰碰车相遇时,它们会立刻掉头(由于速度很快,掉头时间可以忽略)。你可以算出它们在t 秒后的位置吗?
格式
输入格式:第一行有两个数字n(1-1000),t(0一1000),分别表示:碰碰车的数量和所用时间;
接下来n行,每一行都有两个数字:x,f分别表示第n辆碰碰车的位置和方向(0<x≤105,-1表示向左,1表示向右)。
输出格式:输出n行,每一行两个数字,分别表示碰碰车最后的位置和方向(-1表示向左,1表示向右,0表示两车相遇)。
个人思路:
本来是是想着模拟时间和车的进度去实现,后来只过了3个测试点
然后听了王帅康的思路
因为位置相对关系是一定的,然后只需要记录原来的方向,位置,还有排位,再根据规则走下去,
然后此时有了新的位置和排序。
再解决并排问题(防止赋值一一对应的关系被破坏)和最后时刻的相遇问题。
根据新旧车位置排序的一致性,将新生成的对应的车位置信息和方向信息给原来顺序输入序列的车。因为要按照输入的顺序输出

#include<iostream>
using namespace std;
struct car
{
	int x; 
	int nowx;
	int f;
	int nowf;
	int num;
	int fnum;
	
};
car a[1005];
int main()
{
	int n,t;
	cin>>n>>t;
	for(int i=1;i<=n;i++)
	cin>>a[i].x>>a[i].f;

	//排序编码,确定原来的排序位置 
		for(int i=1;i<=n;i++)
		{
		a[i].num++;
		a[i].fnum++;
		}	
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
	{
		if(a[i].x>a[j].x) a[i].num++;
	} 
	//运动后的车位 
    for(int i=1;i<=n;i++)
	{
		if(a[i].f==1) a[i].x+=t;
		if(a[i].f==-1)a[i].x-=t;
	} 
	//低序排序
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
	{
		if(a[i].x>a[j].x) 
		a[i].fnum++;
	}
	//处理并排
	for(int i=1;i<=n;i++)
	for(int j=i+1;j<=n;j++)
	if(a[i].fnum==a[j].fnum) a[i].fnum++;
	//对号入座 
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n;j++)
	{
		//第i号车的原来的相对顺序如果等于移动后那辆车的相对顺序,把当前的车的信息赋值给i车 
		if(a[i].num==a[j].fnum)
		{
		  a[i].nowx=a[j].x;
		  a[i].nowf=a[j].f;
		}
	}    
   //最后的相遇情况
   for(int i=1;i<=n;i++)
   for(int j=i+1;j<=n;j++)
   if(a[i].nowx==a[j].nowx) 
   {
   	a[i].nowf=0;
   	a[j].nowf=0;
   } 
    for(int i=1;i<=n;i++)
	    cout<<a[i].nowx<<" "<<a[i].nowf<<endl;
	   return 0;	
}

 序列操作
难度:黄金时间限制:1秒占用内存:128M
一个共有n个数的单调非递减数列(每个数都是正整数),还有一个整数target,每轮操作可以让数列中满足以下两个要求的数+1:
1.该数比 target小;
2.该数不等于它后面的那个数:
特别地,最后一个数默认满足要求2。
你的任务是求出最小的操作数m,使得第 m轮操作后,该数列中的所有数都等于target(n,target ≤ 100,并且保证数列中任何一个数小于target)。
格式
输入格式:第一行2个正整数n,target(n, target≤100);接下来一行n个正整数,表示这个数列。
输出格式:按题目要求输出一行一个整数,表示最小操作次数。
4 3
1 1 1 1
输出5
个人思路:思路简单
主要是题目难以读懂,一次可以操作多个,但是本次只能操作满足条件的数据。

 

#include<iostream>
using namespace std;
int a[105];
int main()
{
	int n,target,m=0;
	cin>>n>>target;
	for(int i=1;i<=n;i++)
	cin>>a[i];
	while(1)
	{
		//操作次数++ 
		m++;
	for(int i=1;i<=n;i++)
	{
		//i==n时候只要小于就自加 
		if(i==n&&a[i]<target) a[i]++;
        if(i<n)
        {
        	//按照规则操作 
			if(a[i]!=a[i+1]&&a[i]<target) a[i]++; 
		}	
	} 
	//统计此时数组中多少个等于target 
	   int cs=0;
	   for(int i=1;i<=n;i++)
	   if(a[i]==target) cs++;
	   //全是就结束 
	   if(cs==n) break;
	}
	cout<<m;
	
	
	return 0;
	
}

排队
难度:黄金时间限制:1秒占用内存:128M
课间休息做游戏,要求男孩们和女孩们排成一队,最初按照加入队伍的顺序排。然而,过了一会儿,站在女孩们前面的男孩们开始感到尴尬,下一秒,他们会让身后的女孩站到自己前面。
让我们更精确地描述这个过程。假设队列中的位置由1到n的整数顺序编号,我们对位置号1中的人首先进行操作。如果在时间X,男孩站在第i个位置,女孩站在第i+1个位置,然后下一秒,男孩女孩的位置会交换,也就是此时第i个是女孩,第i+1个是男孩。时间是以秒为单位给出的。
你现在知道孩子们的初始位置。确定队列在T秒之后的排列方式。
格式
输入格式:第一行包含两个整数n和t,表示队列中的人数和队列将转换成需要查找的排列的时间;下一行输入一个字符串s,s仅由B和G构成(B表示男孩,G表示女孩)。
输出格式:一个字符串,表示最后的队列。
样例1
输入:51                                                   复制
BGGBG
输出:GBGGB                                              复制
个人思路:思路简单
就是判断当前是不是男孩并且下一个是不是女孩,是就换位置,然后主要的是如果i是男孩,并且i+1是女孩,那么下一次i+1就是男孩,会bug,所以j要++,跳过这个已经换过位置的男孩 

 

#include<iostream>
using namespace std;
int n;//n代表人数
int t;//t代表时间
string s;
int main()
{
	cin>>n>>t;
	cin>>s;
	for(int i=1;i<=t;i++)
	{
		for(int j=0;j<s.size();j++)
		{
			if(s[j]=='B'&&s[j+1]=='G')
			{
				s[j]='G';
				s[j+1]='B';
				j++;
			}
		}	
	} 
	cout<<s;
	return 0;
} 

 小码哥的计划表
难度:黄金时间限制:1秒占用内存:128M
小码哥的寒假有N 天,他做了一个计划表,计划每天做若干数学题目,但是为了平衡每天的任务量,小码哥决定调整一下计划表。他首先设定了每天做题数目的上限R和下限L,然后他准备做一些调整,使得每天的题目数量A;满足L ≤ A;≤R。每次调整小码哥可以把某一天的某些题目换到另一天,每次操作只能移动一道题目。
小码哥请你帮忙算一算需要的最小操作数。
格式
输入格式:第一行一个正整数N,表示计划表的总天数;
第二行N个整数,表示计划表初始每天的题目数;
第三行两个整数L,R。
输出格式:一个数,表示最小的操作数,如果不能满足题目条件输出-1。
个人思路:
第一,就是分别找出低于下限的总量和高于上限的总量
第二,判断能不能弥补
   1.如果能弥补,弥补剩余量给其他,求出答案
   2.不能弥补,随便再继续拿,求出答案
3.刚好弥补,就是答案
   第三,此时不能直接输出ans
          需要判断高于的时候能不能弥补剩余量给别人会不会使别人高于上限,就是遍历一遍上限-a[i],如果结果小于弥补量就说明不行,输出-1并结束
                  需要判断低于的时候能不能拿其他的过来,会不会使别人低于下限,就是遍历一个a[i]-下限,如果结果小于需要弥补的值就说明别人不能给,输出-1结束
 第四,如果上面没有结束,就说明有解,输出ans,结束程序

 

#include<iostream>
using namespace std;
int n;
int l,r;
int ans=0; 
int a[100005];
int main()
{
	cin>>n;
	for(int i=0;i<n;i++)
	cin>>a[i];
	cin>>l>>r;
	//数据处理
	//寻找低于下限的量和高于上限的量 
	int undernum=0,overnum=0;
	for(int i=0;i<n;i++)
	{
	if(a[i]<l)  undernum+=l-a[i];
	if(a[i]>r)    overnum+=a[i]-r;
	}	
	//设置可弥补量
	int take=overnum-undernum;
	//此时说明超出量补充给低于量还有剩余 
	if(take>0) {ans=ans+undernum+take;}
	//此时说超出量补充给低于量不够 
	if(take<0){ans=ans+overnum-take;}
	//此时说超出量补充给低于量刚刚好
	if(take==0) {ans=ans+overnum;} 
	//无法满足的条件下
	//1.低于量无法满足别人给他 
	if(take<0)
		{
			int num=0;
			for(int i=0;i<n;i++)
			num=num+a[i]-l;
			if(num+take<0) 
			{
			cout<<-1;
			return 0;
			}
		}
		//2.高于量无法给别人 
		if(take>0)
		{
			int num=0;
			for(int i=0;i<n;i++)
			num=num+r-a[i];
			if(num<take) 
			{
			cout<<-1;
			return 0;
			}	
		}
	cout<<ans;
	return 0; 	
}

 寻找串
难度:黄金时间限制:1秒占用内存:128M
在所给字符串中找出最少出现两次的最长子串的长度,没有则输出0。
格式
输入格式:这一定是非空的字符串S,并由小写字母组成。
输出格式:输出一个数。这个数是子串中最少出现两次的最长子串的长度。
样例1
输入:ababa                                           复制
输出:3                                               
备注
其中:|S|≤ 100
个人思路:
因为要找长度最长的,所以干脆从最大长度的开始找,又因为重复次数要大于2,所以s.size()就没必要,就从s.size()-1开始
因为长度限制,所以头也有限制,只从0~s.size()-k,这样才不会超出给定字符串
然后以当前长度下的(i~i+k)该串去比对当前长度下的其他串,如果该串的重复次数大于2就是符合题意的最大长度,输出就可以。如果比对没有输出,那就是无解,最后输出0就可以
比对规则:
因为还是当前长度,所以比对的其他串头还是从0~s.size()-lenth
然后每次比对一个新的串都要更新重复字符的次数
定义一个双指针来比对两个串,分别从原串的头和比对的串的头开始,相等重复字符+1,不等就退出,指针每次+1。如果重复的字符数量刚好等于比对长度,说明两个字符串完全相等,那字符串的重复次数就+1;
然后比对完所有当前长度下的串,就直接返回字符串的重复次数。

 

#include<iostream>
using namespace std;
string s;
int num=0,cfnum=0;
int check(int head,int lenth)
{
	for(int i=0;i<=s.size()-lenth;i++)
	{
	//更新当前串和去其他串比对的重复字符 
	cfnum=0;
	int x=i;
	int y=head;
	int t=lenth;
	//要比对长度遍 
	while(t)
	{	
    if(s[x]==s[y])   cfnum++;
     else  break;//不一样直接结束 
	//要比对对应字符,所以比对位数同时自加 
	x++;
	y++;
	//比对一次 
	t--;
	}
	//比对的所有位都相等,该字符串重复+1遍 
	if(cfnum==lenth) num++;
	}
	//比对完成,返回该字符串重复次数 
	return num;	
}
int main()
{
	//输入数据 
	cin>>s;
	//枚举长度 
	for(int k=s.size()-1;k>=1;k--)
	{
	//符合当前长度下的头 i~i+k每个都去比较 
	  for(int i=0;i<=s.size()-k;i++)
	  {
	  	//更新串的重复次数 
	  	num=0;
	  	//用当前s的的字符串中的所有k长度的进行对比
	  	//大于2次就直接结束 
	   if(check(i,k)>=2) {cout<<k;return 0;}
	  }	
	} 
	//上面没有输出结果,就输出0 
	cout<<0;
	return 0;
}

 换换换
难度:钻石时间限制:1秒占用内存:128M
机器人小R在看一个魔术表演,魔术师面前有一排共N 个倒扣着的杯子,其中每一个下面都有一个小玩具t;,并且每个小玩具都是唯一的。魔术师飞快地变换杯子之后让小R猜其中 M 个玩具t在哪个杯子里。由于机器人小R内置的程序只能记录杯子的数量 N,小玩具初始的位置 p,以及魔术师每次变换杯子的位置P1,P2。小R的主人希望你能写一个程序,帮助小R找出玩具。
格式
输入格式:第一行给定三个整数N,M,T,T为魔术师操作的次数;
接下来的N 行,每行给定一个字符串t;;
之后的T行,每行给定两个位置p1,p2,位置从1开始计数;最后M 行,每行给定一个字符串tj。
输出格式:M行,每行一个整数,表示杯子现在的序号。
5 5 5
car
van
track
dog
cat
1 2
4 5
3 2
5 1
1 4
van
car
track
dog
cat
5
3
2
4
1
个人思路:用双for循环进行一 一 对比,但是由于数据是10^5,程序会超时
需要用到新知识:
看了别人的思路:学到了映射函数:  包含于#include<bits/stdc++.h>头文件下
格式  map<string,int>mp;
意思就是  mp[string]=int ;一个字符串对应一个整型数据
那思路就变得很简单了
需要每次交换对应盒子的字符串,还要交换这个字符串的所在盒子编号
最后输出就可以

#include<bits/stdc++.h>
using namespace std;
map<string ,int>mp;
string a[100005];
int n,m,t;
int main()
{
	cin>>n>>m>>t;
	for(int i=1;i<=n;i++)
	{
	cin>>a[i];
	//代表当前第i个玩具在第几号盒子下面 
	mp[a[i]]=i;
	}
	for(int i=1;i<=t;i++)
	{
		int x,y;
		cin>>x>>y;
		//交换x号盒子和y号盒子里面的字符串 
		string temp=a[x];
		a[x]=a[y];
		a[y]=temp;	
		//此时也要交换字符串跑到哪个盒子下面 
		int tem=mp[a[x]];
		mp[a[x]]=mp[a[y]];
		mp[a[y]]=tem;
	}
	//最后只要输入该字符串在哪个盒子下面就可以 
    for(int i=1;i<=m;i++)
    {
	    string s;
		cin>>s;
		cout<<mp[s]<<endl;
	}
	return 0;
}

 

邮箱地址
难度:钻石时间限制:秒占用内存:128M
一个地址由<username>@< hostname>[/resource]组成。
其中和usernamehostname之间只允许有一个@;尖括号<>内包含的为必选项,方括号[]内包含的为可选项。如果出现,则必须跟有resource字段。各字段要求如下:
1.username字段允许大写、小写字母,数字、下划线,其长度应在1到16。
2.hostname字段类似网址,允许用一个或多个来分割,但不允许连续两个连在一起。同时,hostname不允许以,开头或结束。每一段的要求同username字段,分隔出的每一部分长度在1到16hostname字段的总长度在1到32。
3.resource字段要求同字段,不限制长度。username
现给出一个地址,请判断是否合法。
格式
输入格式:一行,一个字符串,表示一个地址(保证地址的字符的ASCII在33到127间),地址长度不超过1000字符。
输出格式:一行,如果合法输出YES,否则输出NO。
样例1
输入:123@npu.com
输出:YES
复制
复制

个人思路:总体来说没有很大难度,就跟着要求来就行
就是把每一个部分独立分割出来,然后再按照要求去判断
特别要注意的就是要先判断指针指的位置有没有超出字符串的长度再去指,不然就会造成指针的超出导致返回值出现错误

#include<iostream>
using namespace std;
int main()
{
	string s;
	cin>>s;
	int t1=0,t2=0,t3=0;
	char a1[30],a2[100];
	//第一部分存于数组a1的0~t1;因为算到@,方便计算最后t1-- 
	while(s[t1]!='@')
	{
		a1[t1]=s[t1];
		t1++;
	} 
	t1--; 
	//判断第一部分
	//规则一:长度是[1,16]
	if(t1+1>16||t1+1<1) {cout<<"NO"; return 0; }
	//规则二:只能有大写字母或小写字母
	//        或者数字或者下划线 
	for(int i=0;i<=t1;i++)
	{
		//
		if(!((a1[i]>='A'&&a1[i]<='Z')||(a1[i]>='a'&&a1[i]<='z') ||(a1[i]-'0'>=0&&a1[i]-'0'<=9)||(a1[i]=='_')) )
		{
		cout<<"NO";
		return 0;
		}
	}
	//查找第一二部分中间是否只有一个@ 
	//意思就是不能是多个@ 
	//因为t1指的是@前面那个,所以t2要从小老鼠后1位开始查看
	for(int i=t1+2;i<s.size();i++)
	{
		if(s[i]=='@')
		{
			cout<<"NO";
			return 0;
		}
	}
	//开始生成第二部分
	//从t2开始知道遇到/或者没有字符
	//存储区间为t22~t2-1,因为算到/,方便计算最后t2-- 
	int t22=t1+2;
	t2=t1+2; 
	while(t2<s.size()&&s[t2]!='/'&&s[t2]!=' ')
	{
		a2[t2]=s[t2];
		t2++;
		//超出长度结束,防止指针出错 
		if(t2==s.size()) break;
	}  
	t2--;
	//判断第二部分
	//判断规则
	//1.头尾不是点
	//2.不连续为.
	//3.两个点之间的长度为1-16
	//4.总长度为1-32 
	//5.	只能有大写字母或小写字母
	//        或者数字或者下划线 
    //6.判断第二部分的必选项是否存在
	//1 
    if(a2[t22]=='.'||a2[t2]=='.')
    {
		cout<<"NO";
		return 0;
	}
	//2
	for(int i=t22;i<=t2;i++)
	{
		if(a2[i]=='.'&&a2[i+1]=='.') 
		{
			cout<<"NO";
			return 0;
		}
	}
	//3
	int flag=0;
	int first=0; 
	int head,rear;
	for(int i=t22;i<=t2;i++)
	{
		//检测到. 
		if(a2[i]=='.')
		{   
		     //如果是第一段那就只需要右端点的点 
		 if(first==0)    first++;
		 else first=-1;
			//标记遇到几个点 
			flag+=1;
			//当点已经两个就可以查询中间的长度
			if(first==1)
			{
				rear=i;
				if(rear-t22>16||rear-t22<1)
				{
					cout<<"NO";
					return 0;
				}
			} 
			if(flag==2)
			{
				//把尾巴标记为当前的i ,头是上次的点 
			   rear=i;
			   //计算长度 
			    
		     	if(rear-head-1>16||rear-head-1<1) 
			    {
		  		cout<<"NO";
				return 0;
			    }
			    //因为当前也是点,所以更新flag为1 
				flag=1;
			}
			//并且最新查到的点更新为头 
			head=i;
		}
	}
	//4,可包含点 
	if(t2-t22+1>=32) 
	{
		cout<<"NO";
		return 0;
	}
	//5
		for(int i=t22;i<=t2;i++)
		{
			if(!((a2[i]>='A'&&a2[i]<='Z')||(a2[i]>='a'&&a2[i]<='z') ||(a2[i]-'0'>=0&&a2[i]-'0'<=9)||(a2[i]=='_')||a2[i]=='.' ))
			{
			cout<<"NO";
			return 0;
			}
		}
		//6
		if(t22==s.size())
		{
			cout<<"NO";
			return 0;
		}
	//判断第三部分
	//因为t2指的是/前一位,所以/是t2+1
	//如果第三部分存在
	if(t2+1<s.size()&&s[t2+1]=='/') 
	{
		//因为出现/ 所以必须跟有recouse字段
		//如果此时出现/而没有字段 
		   if(t2+2==s.size())
		   {
		   	cout<<"NO";
			return 0; 
		   }
		//出现/ 并且有recouse字段	
		//只能有大写字母或小写字母
		//        或者数字或者下划线,不限制长度 
		t3=t2+2;
		//遍历字符串剩余的部分 
	    for(int i=t3;i<s.size();i++)
		{
			if(!((s[i]>='A'&&s[i]<='Z')||(s[i]>='a'&&s[i]<='z') ||(s[i]-'0'>=0&&s[i]-'0'<=9)||(s[i]=='_')) )
	     	{
			cout<<"NO";
			return 0; 
			}	
		}	
	} 
	//上述情况均不存在,说明字符串合法 
	cout<<"YES";
    return 0;
}

 

给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。

        7
      3   8
    8   1   0
  2   7   4   4
4   5   2   6   5
输入格式
第一行包含整数 n,表示数字三角形的层数。

接下来 n 行,每行包含若干整数,其中第 i 行表示数字三角形第 i 层包含的整数。

输出格式
输出一个整数,表示最大的路径数字和。

数据范围
1≤n≤500,
−10000≤三角形中的整数≤10000
输入样例:
5
7
3 8
8 1 0 
2 7 4 4
4 5 2 6 5
输出样例:
30
个人思路就是当前点位的最大值是上面左右两个点位的最大值再上当前点位的值
需要特别注意的每行的左右两个点,因为这两个点只能从上一行的最左边和最右边下来
另外的就不用特殊考虑了
然后执行完成后在最后一行寻找最大的答案,还需要注意的是因为最后答案可能为负数,所以ans的初值要为很小的负数,如果设置0 ,那就会出现错误
 

 

#include<iostream>
using namespace std;
int a[505][505];
int n = 0;
long long ans = -1000000000000;
long long dp[505][505];
int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= i; j++)
			cin >> a[i][j];
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= i; j++)
		{
			if (j == 1)  dp[i][j] = dp[i - 1][j] + a[i][j];
			else if (j == i) dp[i][j] = dp[i - 1][j - 1] + a[i][j];
			else dp[i][j] = max(dp[i - 1][j - 1], dp[i - 1][j]) + a[i][j];
		}
	for (int i = 1; i <= n; i++)
		if (ans < dp[n][i]) ans = dp[n][i];
	cout << ans << endl;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值