某csdn大佬推荐的新手刷题网站,快速入门!洛谷
新手入门刷题(专题一)模拟与高精度(第二部分)———>持续更新
4月4日
[USACO2.4]两只塔姆沃斯牛 The Tamworth Two
题目描述
略,见题目链接
思路
无解的情况:
当牛和人同时再次出现在之前走过的地方,且牛和人的方向相同时,判断为无解
bool len[2000000];
//牛x+牛y*10+牛方向*100+人x*1000+人y*10000+人方向*100000,唯一值
int st = (x_c-1) + (y_c-1)*10 + (x_f-1)*100 + (y_f-1)*1000 + f_c * 10000 + f_f *100000;
if(!len[st]) len[st] = true;
else{
cout<<0;
return 0;
}
代码
#include<iostream>
#include<cstring>
using namespace std;
bool len[2000000];
//把移动单独拎出来
void move(int &flag,char a[][12],int &x,int &y){
//先判断方向,再判断该方向下一步是否为障碍物
//上
if(flag==0&&a[x-1][y]!='*'){
char t = a[x-1][y];
a[x-1][y] = a[x][y];
a[x--][y] = t;
//右
}else if(flag==1&&a[x][y+1]!='*'){
char t = a[x][y+1];
a[x][y+1] = a[x][y];
a[x][y++] = t;
//下
}else if(flag==2&&a[x+1][y]!='*'){
char t = a[x+1][y];
a[x+1][y] = a[x][y];
a[x++][y] = t;
//左
}else if(flag==3&&a[x][y-1]!='*'){
char t = a[x][y-1];
a[x][y-1] = a[x][y];
a[x][y--] = t;
//转向
}else flag = (flag+1)%4;
}
int main(){
//数组多两行两列,使其边界全是障碍物
char a[12][12],b[12][12];
memset(a,'*',12*12);
memset(b,'*',12*12);
int x_c,x_f,y_c,y_f;
//牛和人分开到两个数组,防止出现人牛无限循环
for(int i=1;i<=10;i++){
for(int j=1;j<=10;j++){
cin>>a[i][j];
//a数组放牛,b数组放人
a[i][j]=='C'?b[i][j]='.':b[i][j]=a[i][j];
if(a[i][j]=='F') a[i][j]='.';
if(a[i][j]=='C') x_c=i,y_c=j;
if(b[i][j]=='F') x_f=i,y_f=j;
}
}
int f_c,f_f,times;
f_c=f_f=times=0;
while(1){
int st = (x_c-1) + (y_c-1)*10 + (x_f-1)*100 + (y_f-1)*1000 + f_c * 10000 + f_f *100000;
//如果人和牛走到原来的路和原来的方向,循环结束,判断为误解
if(!len[st]) len[st] = true;
else{
cout<<0;
return 0;
}
move(f_c,a,x_c,y_c);
move(f_f,b,x_f,y_f);
times++;
//如果人和牛的定位相同,循环结束,输出步数
if(x_c==x_f&&y_c==y_f){
break;
}
}
cout<<times;
return 0;
}
[NOIP2009 普及组] 多项式输出
题目描述
模拟一元多项式(第二个觉得简单的题目),详见题目链接
思路
考虑三个方面:系数、次方、常数
系数为零,多项式正负号,系数为正负1时
次方大于1以及等于1的情况
前有多项式时,常数正负号,以及常数为0
前无多项式时,常数正负号,以及常数为0
代码
#include<iostream>
using namespace std;
int main(){
int a;
cin>>a;
int b[a+1];
for(int i=0;i<a+1;i++){
cin>>b[i];
}
int t = a;
//处理到常数之前
for(int i=0;i<a;i++){
//系数为0,只执行次方递减,
if(b[i]==0){
t--;
continue;
}
//系数为正数且不为第一个数时添加加号
if(b[i]>0&&i!=0) cout<<'+';
//系数不为1或-1时输出系数
if(b[i]*b[i]!=1) cout<<b[i];
//系数为-1时输出负号
if(b[i]==-1) cout<<'-';
//次方大于1时显示自变量x和次方t
if(t>1) cout<<"x^"<<t;
//次方等于1时只显示自变量x
if(t==1) cout<<"x";
t--;
}
//常数单独拎出来
//只有常数直接输出
if(a==0) cout<<b[a];
//前有自变量x,判断常数正负号以及是否为零
else if(b[a]>0) cout<<'+'<<b[a];
else if(b[a]<0) cout<<b[a];
}
4月5日
[NOIP2007 提高组] 字符串的展开
题目描述
将字符串折叠部分按规则展开,详见题目链接
思路
首先要考虑什么情况需要展开,比如 a-z、0-9、a-b、0-1等情况需要展开
什么情况不能展开,比如 -sdxva55、as35-、a-0、0-a、—、0-0、a-a、z-a、9-0等情况无需展开
其次对展开步骤进行分析
先考虑大写情况,只有字母展开需要大写,因此当规则为大写时,只分析字母就行;
接着,无论是大写情况下的数字,还是小写情况下的字母或数字,可以放一起考虑;
最后是*情况,这种情况比较简单
重复情况直接在输出时叠加for循环即可
逆序或顺序放在最外层考虑。
关于代码中的疑点,a[i+1] - a[i-1] < 26,因为字符 a - z 最大情况为 26,0 - 9 最大情况为 10,具体可查看ascii码表,但是有一种情况也满足 a[i+1] - a[i-1] < 26 ,那就是 - - 0 ,- 的 ascii 码为 45 ,0 的 ascii 码为 48 ,因此二者相减也小于26,但是这种情况是不能展开的,故当 a[i-1] ! = ‘-’。
代码
#include<iostream>
using namespace std;
char a[100000];
//展开操作
int ext(char a,char c,int x,int y,int z){
//正序展开
if(z==1){
//转成大写的情况
if(x==2&&'a'<=a&&a<='z'&&'a'<=c&&c<='z'){
for(char i=a-31;i<c-32;i++){
for(int j=0;j<y;j++){
cout<<i;
}
}
//不用转成大写的情况
}else if(x==1||x==2){
for(char i=a+1;i<c;i++){
for(int j=0;j<y;j++){
cout<<i;
}
}
//转成*的情况
}else{
for(char i=a+1;i<c;i++){
for(int j=0;j<y;j++){
cout<<'*';
}
}
}
//逆序展开
}else if(z==2){
//转成大写的情况
if(x==2&&'a'<=a&&a<='z'&&'a'<=c&&c<='z'){
for(char i=c-33;i>=a-31;i--){
for(int j=0;j<y;j++){
cout<<i;
}
}
//不用转成大写的情况
}else if(x==1||x==2){
for(char i=c-1;i>=a+1;i--){
for(int j=0;j<y;j++){
cout<<i;
}
}
//转成*的情况
}else{
for(char i=c-1;i>=a+1;i--){
for(int j=0;j<y;j++){
cout<<'*';
}
}
}
}
}
int main(){
int p1,p2,p3;
cin>>p1>>p2>>p3;
char t;
int la=0;
while(cin>>t) a[la++]=t;
for(int i=0;i<la;i++){
//当'-'不在头和尾、且'-'的前一位<'-'的后一位、且后一位减去前一位小于26、且前一位不是'-'时才能展开
if(a[i]=='-'&&i!=0&&i!=la-1&&a[i-1]<a[i+1]&&a[i+1]-a[i-1]<26&&a[i-1]!='-'){
ext(a[i-1],a[i+1],p1,p2,p3);
}else{
cout<<a[i];
}
}
}