这是第一题:https://www.luogu.org/problemnew/show/P1085
这道题,没有什么好说的吧,就是暴力枚举就好了
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
int a,b,s,max=0,i,day=0;//a和b是津津每天上课的时间,s是上课时间之和
int main ()
{
freopen("unhappy.in","r",stdin);
freopen("unhappy.out","w",stdout);
for(i=1;i<8;i++){
cin>>a>>b;
s=a+b;
if ((s>max)&&(s>8)){
max=s;
day=i;
}//在超过8小时且比之前几天都大的s时,将s赋给最大值,并记录下JJ的这天
}
cout<<day<<endl;//由于刚开始day的初值就是0,如果每一天都开心的话,直接输出就好了
return 0;
}
这是第二题:https://www.luogu.org/problemnew/show/P1086
这道题,刚开始的时候,题目理解错了,本意应该是“一直找最大的,直到没有时间为止”,但是我却理解成为了“在单位时间里面所能获得的最大价值”,这就很尴尬了。。。
言归正传,这道题其实模拟就好了啊
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<utility>
#include<cmath>
#include<cstdio>
using namespace std;
int m,n,k=1,t,u,ans;
struct peanuts{
int x,y,time,w;
}p[1000001];//(x,y)为坐标,time为时间,w表示数量
int a[1010][1010];
void qsort(int l,int r)
{
if(l>=r)
return;
int t=p[rand()%(r-l+1)+l].w;
int i=l,j=r;
while(i<=j){
while(p[i].w>t)i++;
while(p[j].w<t)j--;
if(i<=j){
swap(p[i],p[j]);
i++;
j--;
}
}
qsort(l,j);
qsort(i,r);
}
int main()
{
cin>>m>>n>>t;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
cin>>a[i][j];
if(a[i][j]>0){//当有花生的时候。。。
p[k].w=a[i][j];
p[k].x=i;
p[k].y=j;
k++;
}
}
}
srand(100000000);
qsort(1,k);
for(int i=1;i<=k;i++){
u=p[i].x;
//由于我们要考虑多多采花生返回,而返回的路程就是深度即x,如果加上这个x可以按时返回的话就采这个花生。
if(i==1)
p[i].time=p[i].x+1;
//第一个花生是不同的,因为多多一开始可以跳到第一个最多花生的所在列
else
p[i].time=p[i-1].time+abs(p[i].x-p[i-1].x)+abs(p[i].y-p[i-1].y)+1;
//不是第一个的话就加上与前一个的坐标差再加采摘时间
if(p[i].time+u<=t)
ans+=p[i].w;
//如果数据合法那么就把花生数加上就好了
}
cout<<ans<<endl;
return 0;
}
这里是第三题:https://www.luogu.org/problemnew/show/P1087
这道题,大概可以分为三步:
1.建树。按照题意是在递归过程中建立树,建树的方法实际上就是树的先序遍历(先根节点,再左右子树)。当本节点长度大于1时递归建立子树。
2.输出。而输出过程是对树的后序遍历(先左右子树,再根节点),这里有个技巧就是可以和建树过程集成在一起。只需将代码放在递归调用之后就可以了。
3.判断。最后是判断当前节点的FBI树类型,可以用B(初始值为1)保存全是‘0’的情况,如果遇到‘1’就将B置为0,用I(初始值为1)保存全是‘1’的情况,如果遇到‘0’就将I置为0。最后判断B和I中的值,如果两个都为0则输出F(不全为‘0’,不全为‘1’)。
讲完步骤,我们来讲一点实现方面的东西,我们可以用前缀和来存储一的个数(在这个数里面的值不是一,就是零,所以数值是多少,就代表有多少个一)。
最后,附上代码~~~
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
int n,s[2000];
string a;
void prepare()
{
s[0]=a[0]-'0';
for(int i=1;i<(1<<n);++i)
s[i]=s[i-1]+a[i]-'0';//维护一个前缀和
}
void maketree(int l,int r)
{
if(l<r){
maketree(l,(l+r)/2);
maketree((l+r+1)/2,r);
}
int k=s[r]-s[l-1];//统计从l到r这个区间里面有多少个一
if(k==0)//全部都是零的时候才会是'B'
cout<<"B";
else if(k==(r-l+1))//全部都是一的时候才会是'I'
cout<<"I";
else//剩余情况都是'F'
cout<<"F";
}
int main()
{
cin>>n>>a;
prepare();
maketree(0,(1<<n)-1);
cout<<endl;
return 0;
}
终于到了第四题了,题目在这里:https://www.luogu.org/problemnew/show/P1088
这道题嘛,直觉告诉我模拟一下深度优先搜索,就是说第一次搜索的时候直接到达外星人给出的那个结点,然后再慢慢往回推。等到求到的全排列是外星人给出的加上我们要加的数字时,就大功告成了!!!
最后附上代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
const int maxn=10010;
int n,m,a[maxn],flag,flagx;
bool s[maxn];
void dfs(int step)
{
if(flagx==1)
return;
if(step>n){
flag++;
if(flag==m+1){
//现在到了我们要加上的那个数的全排列的时候
//我们就直接地输出,然后标记flagx,一直return,结束程序
for(int j=1;j<=n;j++)
cout<<a[j]<<" ";
cout<<endl;
flagx=1;
}
return;
}
for(int i=1;i<=n;i++){
if(flag==0)
i=a[step];
//当还在外星人给出的排列这个阶段的时候,我们就直指外星人给出的序列中的数
if(s[i]==0){
s[i]=1;
a[step]=i;
dfs(step+1);
s[i]=0;
}
}
}
int main()
{
freopen("martian.in","r",stdin);
freopen("martian.out","w",stdout);
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
dfs(1);
return 0;
}