T1:特殊正方形
题目链接:特殊的正方形 - 题目 - Daimayuan Online Judge
题解:
用一个cnt记录打印的圈数,当cnt为奇数时候打印“+”,偶数时候打印“.”
在对应打印函数传入起点k及打印的高度h
代码
#include<bits/stdc++.h>
using namespace std;
int n;
char m[105][105];
void pr_1(int h,int k){//h为打印的高度,k为打印的起点
for(int i=k;i<=h;i++){
for(int j=k;j<=n-k+1;j++){
if(i==k||i==h)m[i][j]='+';
else m[i][k]='+',m[i][n-k+1]='+';
}
}
}
void pr_2(int h,int k){
for(int i=k;i<=h;i++){
for(int j=k;j<=n-k+1;j++){
if(i==k||i==h)m[i][j]='.';
else m[i][k]='.',m[i][n-k+1]='.';
}
}
}
int main()
{
cin>>n;
int cnt=1;
for(int i=n;i>=1;i--){
if(cnt%2)pr_1(i,cnt);
else pr_2(i,cnt);
cnt++;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout<<m[i][j];
}
cout<<endl;
}
return 0;
}
T2:走楼梯2
题目链接:走楼梯2 - 题目 - Daimayuan Online Judge
题解:
用一个f[i][j]记录走到i级阶梯连续j次走两步的路径数,显然:到达第n级台阶的总路径数是f[n][0]+f[n][1]+f[n][2]
- 走两步:f[i+2][j+1]当j<2时候可以从f[i][j]转移
- 走一步:f[i+1][0]可以从f[i][1],f[i][2]和f[i][0]转移
- 初始化f[0][0]=1;然后从0步开始走
代码
#include<bits/stdc++.h>
using namespace std;
long long n,f[105][4];
int main()
{
cin>>n;//初始化
f[0][0]=1;
for(int i=0;i<=n;i++){
for(int j=0;j<=2;j++){
if(j<2){//状态转移
f[i+2][j+1]+=f[i][j];
f[i+1][0]+=f[i][j];
}
else{
f[i+1][0]+=f[i][j];
}
}
}
cout<<f[n][0]+f[n][1]+f[n][2]<<endl;//输出撒花
return 0;
}
T3:走路
题目链接:走路 - 题目 - Daimayuan Online Judge
题解:
用f[i][j]表示走i步是否到达坐标为j的位置,用“1”代表能够到达,用"0"代表不能够到达.
若f[i][j]==1且j+a[i]或者j+b[i]小于坐标最大值m则f[i+1][j+a[i]]或f[i+1][j+b[i]]就能到达
最后输出n步之后能够到达的点
代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[105],b[105],f[105][100005];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i]>>b[i];
}
f[0][0]=1;//从0步开始走
for(int i=0;i<n;i++){
for(int j=0;j<=m;j++){
if(f[i][j]&&j+b[i]<=m)f[i+1][j+b[i+1]]=1;
if(f[i][j]&&j+a[i]<=m)f[i+1][j+a[i+1]]=1;
}
}
for(int i=0;i<=m;i++){
if(f[n][i]==1)cout<<1;
else cout<<0;
}
return 0;
}
T4:简单分数统计
题目链接:简单分数统计 - 题目 - Daimayuan Online Judge
模拟题,开水
#include<bits/stdc++.h>
using namespace std;
int n,m,k,sum[205];
string id[205];
struct x{
int s;
string title;
}x[205];
int main()
{
cin>>n>>m>>k;
for(int i=1;i<=n;i++)cin>>id[i];
for(int i=1;i<=m;i++)cin>>x[i].title>>x[i].s;
for(int i=1;i<=k;i++){
string a,b,c;
cin>>a>>b>>c;
if(c=="WA")continue;
int flag=0,now=0;
for(int j=1;j<=m;j++){
if(b==x[j].title){
flag=1;now=x[j].s;
break;
}
}
if(flag){
for(int j=1;j<=n;j++){
if(a==id[j]){
sum[j]+=now;
break;
}
}
}
}
for(int i=1;i<=n;i++){
cout<<id[i]<<' '<<sum[i]<<endl;
}
return 0;
}
T5:Alice的德州扑克
题目链接:Alice的德州扑克 - 题目 - Daimayuan Online Judge
恶心的模拟题~~~,用建立结构体一个一个检查就行了
#include<bits/stdc++.h>
using namespace std;
struct pai{
int ditgit,color;
}p[10];
string rk[7]={"ROYAL FLUSH","STRAIGHT FLUSH","FOUR OF A KIND","FULL HOUSE","FLUSH", "STRAIGHT","FOLD"};
bool RF(){
int x=p[1].ditgit,y=p[1].color;
if(p[5].ditgit!=14)return 0;
for(int i=2;i<=5;i++){
if(x+1!=p[i].ditgit||y!=p[i].color)return 0;
x++;
}
return 1;
}
bool SF(){
int x=p[1].ditgit,y=p[1].color;
for(int i=2;i<=5;i++){
if(x+1!=p[i].ditgit||y!=p[i].color)return 0;
x++;
}
return 1;
}
bool FK(){
if(p[1].ditgit==p[4].ditgit)return 1;
else if(p[2].ditgit==p[5].ditgit)return 1;
else return 0;
}
bool FH(){
if(p[1].ditgit==p[3].ditgit&&p[4].ditgit==p[5].ditgit)return 1;
else if(p[1].ditgit==p[2].ditgit&&p[3].ditgit==p[5].ditgit)return 1;
else return 0;
}
bool F(){
int c=p[1].color;
for(int i=2;i<=5;i++){
if(c!=p[i].color)return 0;
}
return 1;
}
bool S(){
int x=p[1].ditgit;
for(int i=2;i<=5;i++){
if(x+1!=p[i].ditgit)return 0;
x++;
}
return 1;
}
int main()
{
for(int i=1;i<=5;i++)cin>>p[i].ditgit;
for(int i=1;i<=5;i++)cin>>p[i].color;
if(RF())cout<<rk[0];
else if(SF())cout<<rk[1];
else if(FK())cout<<rk[2];
else if(FH())cout<<rk[3];
else if(F())cout<<rk[4];
else if(S())cout<<rk[5];
else cout<<rk[6];
return 0;
}
T6:订单编号
最让人头疼的一题,呜呜~~~
题目链接:订单编号 - 题目 - Daimayuan Online Judge
题解:(做这种难题确实让人收获颇盛,但是很耗时间)
一个个知识点梳理:
1:stl容器之set:在集合中所有的元素只能出现一遍,并且按照元素的值从小到大排序
- set.insert(ele)向集合中插入一个元素ele
- set.erase(index/ele)删除集合中迭代器index指向的元素,或者直接删除元素ele
- set.lower_bound(key)返回集合中第一个大于等于key的迭代器
- set.upper_bound(key)返回集合中第一个大于key的迭代器
2:当set与pair组合使用时候,low_bound查找的是first的值,如果first相同情况下,才会查找second
正文:
为啥要反着储存set(2e9,1)而不是set(1,2e9)呢?
我是这莫理解的:如果正向储存,查找到的总是一个大于x的数的迭代器位置,这样的话是始终找不到一个区间(L,R)包含x的情况
情况1:当查找到的区间最小值L小于等于x时候,说明这个订单编号未被使用,删除这个it迭代器对应的元素将区间(L,R)分为两段(L,x-1)和(x+1,R)
情况2:当查找到区间的最小值L大于x时候,说明这个订单编号已经被使用过了,只能使用区间中第一个大于x的订单编号L,然后将区间(L,R)变化为(L+1,R);
代码段
#include<bits/stdc++.h>
using namespace std;
int n;
set<pair<int,int> > s;
void Insert(int l,int r){
if(l>r)return;
s.insert(make_pair(r,l));
}
int main()
{
scanf("%d",&n);
s.insert(make_pair(2e9,1));//反向储存
for(int i=1;i<=n;i++){
int x;
scanf("%d",&x);
auto it=s.lower_bound(make_pair(x,0));//查找第一个大于x的pair.first()迭代器位置
int l=it->second,r=it->first;
s.erase(it);
if(l<=x){
printf("%d ",x);
Insert(l,x-1);//裂开区间
Insert(x+1,r);
}
else{
printf("%d ",l);
Insert(l+1,r);
}
}
return 0;
}
T7:饿饿饭饭
题目链接:http://oj.daimayuan.top/course/11/problem/463
题解:二分答案一共打了多少轮饭,然后将最后一轮的情况,进行模拟队列(真滴6)
代码段:
#include<bits/stdc++.h>
using namespace std;
int n,a[100005],c[100005];
long long k;
long long res(int x){
long long sum=0;
for(int i=1;i<=n;i++){
if(a[i]<=x)sum+=a[i];
else sum+=x;
}
return sum;
}
int main()
{
cin>>n>>k;
long long s=0;
for(int i=1;i<=n;i++)cin>>a[i],s+=a[i];
if(s<k){
cout<<-1;
return 0;
}
int L=0,R=1e9;
while(L+1<R){二分轮数
int mid=(L+R)/2;
if(res(mid)<=k)L=mid;
else R=mid;
}
//模拟最后一轮打饭情况
k-=res(L);
int tot=0;
for(int i=1;i<=n;i++){
if(a[i]>L)c[++tot]=i;
}
for(int i=k+1;i<=tot;i++){
cout<<c[i];
}
for(int i=1;i<=k;i++){
if(a[c[i]]!=L+1)
cout<<c[i];
}
return 0;
}
T8:最大和上升子序列
题目链接:最大和上升子序列 - 题目 - Daimayuan Online Judge
思路:
当i前面的数满足小于a【i]时候,更新对应于f[i]的最佳答案
代码段:
#include<bits/stdc++.h>
using namespace std;
int n,a[1005],f[1005],vis[100005],ans;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
f[i]=a[i];//初始化
}
for(int i=2;i<=n;i++){
for(int j=1;j<i;j++){//循环i前面的数
if(a[j]<a[i])f[i]=max(f[i],f[j]+a[i]);//更新f[i]答案
ans=max(ans,f[i]);//搜索最大答案
}
}
ans=max(ans,f[1]);
cout<<ans<<endl;
return 0;
}