1、特殊的正方形
思路:
这题用二维数组一圈一圈地存更简便,但我当时没想到,所以我直接暴力解题,一行一行的存。不要学我暴力解题!代码稍微看看就行了,不太记得自己的代码思路了,可以说思路很乱,所以代码请不要深究。
#include<iostream>
using namespace std;
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)cout<<"+"; //先输出第一行
cout<<endl;
int u; //u表示除了第一行和最后一行,中间行数的均值
if(n%2==0)u=(n-2)/2;
else u=(n-2)/2+1;
for(int j=1;j<=n-2;j++)//现只对中间的行做分析,故j=1表示第二行,以下称为第j行
{
int m=1,js;
if(n%2==0)
{
if(j<=u)js=j;
else js=2*u+1-j;
}
else
{
if(j<=u)js=j;
else js=2*u-j;
}
int u1=js;
while(m<=n)
{
if(m%2==1&&js>0)
{
cout<<"+";
js--;
}
else if(m%2==0&&js>0)
{
cout<<".";
js--;
}
else if(js==0&&n-m>=u1)
{
if(u1%2==1)
{
cout<<".";
}
else cout<<"+";
}
else
{
if(n%2==0)
{
if(m%2==0)cout<<"+";
else cout<<".";
}
else
{
if(m%2==0)cout<<".";
else cout<<"+";
}
}
m++;
}
cout<<endl;
}
for(int i=0;i<n;i++)cout<<"+";
return 0;
}
2、走楼梯2
思路:
典型的动态规划题。本题关键在于找到状态转移方程
dp[i][0] = dp[i-1][0]+dp[i-1][1]+dp[i-1][2]
注意:当站在第 k 阶时,要考虑三种情况:
1、一步一阶登上第 k 阶
2、一步两阶,且第一次是一步两阶
3、一步两阶,且连续两次是一步两阶
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include <iomanip>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
#define fo(x) for(int i = 1;i<=x;++i)
#define ios ios::sync_with_stdio(false);cin.tie(0), cout.tie(0)
const int N = 1e6+9;
ll dp[55][5];
int main()
{
ios;
int n;
cin>>n;
dp[1][0] = 1;
dp[1][1] = 0;
dp[1][2] = 0;
dp[2][0] = 1;
dp[2][1] = 1;
dp[2][2] = 0;
for(int i = 3;i<=n;i++)
{
dp[i][0] = dp[i-1][0]+dp[i-1][1]+dp[i-1][2];
dp[i][1] = dp[i-2][0];
dp[i][2] = dp[i-2][1];
}
cout<<dp[n][0]+dp[n][1]+dp[n][2]<<"\n";
}
3、走路
思路:
如果只是把所有情况都考虑一次,这样会超时。可以用动态规划的方法解答,同样的,需找到状态转移方程st[i][j] = st[i - 1][j - a]
#include<iostream>
using namespace std;
const int N = 100010;
int n, m;
bool st[110][N];
int main()
{
cin >> n >> m;
st[0][0] = true;
for ( int i = 1; i <= n; i ++ )
{
int a, b;
cin >> a >> b;
if (a > b) swap(a, b);
for ( int j = m; j >= a; j -- )
{
st[i][j] = st[i - 1][j - a];
if (j >= b) st[i][j] = st[i - 1][j - b];
}
}
for ( int i = 0; i <= m; i ++ )
{
if (st[n][i]) cout << "1";
else cout << "0";
}
return 0;
}
4、简单分数统计
思路:
这题很简单,就是模拟,按照题目说的做就行了。
#include<iostream>
using namespace std;
struct fr //保存好朋友的数据
{
string id; //名字
int s; //分数
};
struct q //保存题目的情况
{
string q1; //题目名称
int q2; //题目分数
};
int main()
{
int n,m,k;
cin>>n>>m>>k;
fr a[n+1];
q b[m+1];
for(int i=1;i<=n;i++)
{
cin>>a[i].id;
a[i].s=0;
}
for(int i=1;i<=m;i++)
{
cin>>b[i].q1>>b[i].q2;
}
for(int i=1;i<=k;i++)
{
string name,sub,r;
cin>>name>>sub>>r;
for(int j=1;j<=n;j++)
{
if(a[j].id==name&&r=="AC")
{
for(int h=1;h<=m;h++) //判断对应的题目加对应的分数
{
if(b[h].q1==sub)a[j].s+=b[h].q2;
}
}
}
}
for(int i=1;i<=n;i++)
cout<<a[i].id<<' '<<a[i].s<<endl;
return 0;
}
5、Alice的德州扑克
思路:
这题也比较简单,也是模拟,注意看清楚题目、注意牌型有大小之分。
#include<iostream>
using namespace std;
int main()
{
int a[6],b[6],c[15]={0}; //a数组用于表示牌的点数,b表示花色,c用于统计每种牌有多少张
int flag1=0,flag2=0,flag3=0;
for(int i=1;i<=5;i++)
{
cin>>a[i];
c[a[i]]++;
}
for(int i=2;i<=14;i++)
{
if(c[i]>=4) //至少四张牌的点数相同
{
flag1=4;
}
else if(c[i]==3) //至少三张牌的点数相同
{
flag2=3;
}
else if(c[i]==2) //出现有两张牌点数相同的情况
{
flag3=2;
}
}
for(int i=1;i<=5;i++)cin>>b[i];
if(a[2]-a[1]==1&&a[3]-a[2]==1&&a[4]-a[3]==1&&a[5]-a[4]==1)
{
if(b[1]==b[2]&&b[2]==b[3]&&b[3]==b[4]&&b[4]==b[5])
{
if(a[5]==14)cout<<"ROYAL FLUSH";
else cout<<"STRAIGHT FLUSH";
}
else cout<<"STRAIGHT";
}
else if(flag1==4)cout<<"FOUR OF A KIND";
else if(flag3==2&&flag2==3)cout<<"FULL HOUSE";
else if(b[1]==b[2]&&b[2]==b[3]&&b[3]==b[4]&&b[4]==b[5])
{
cout<<"FLUSH";
}
else cout<<"FOLD";
return 0;
}
6、订单编号
思路:
set用法:set排序遇到pair,lower_bound查的是set的first,不会查second,除非first相等才会按照second来排。查到的时候只需要观察是否在区间内即可,(如果区间的最小值大于等于x就直接输出x,如果区间最小值大于x就输出区间最小值)查到之后将该点去掉分成两个区间。插入pair时需要用insert,并且带上大括号{}。
(C++中set用法详解)
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
typedef vector<int> vi;
//#define int long long
#define fir first
#define sec second
#define all(x) (x).begin(), (x).end()
#define sz(x) (int)x.size()
#define rep(i, l, r) for (int i = l; i <= r; ++i)
#define repd(i, l, r) for (int i = l; i >= r; --i)
#define pb push_back
set<pair<int,int> >se;
void myinsert(int l,int r)
{
if(r<l)return;
se.insert({r,l});
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL); //对cin解绑
int n;
cin>>n;
se.insert({2e9,1});
rep(i,1,n)
{
int x;
cin>>x;
auto it=se.lower_bound({x,0});
if(it->sec <=x)
{
cout<<x<<" ";
myinsert(it->sec,x-1);
myinsert(x+1,it->fir);
se.erase(it);
}
else
{
cout<<it->sec<<" ";
myinsert(it->sec+1,it->fir);
se.erase(it);
}
}
return 0;
}
7、饿饿 饭饭
思路:
用一个map记录所有学生的饭量的出现次数,因为map的自动排序功能,使得小饭量的会排在前面。把学生的饭量按照输入顺序存入数组中,同时记录所有饭量的总和,如果总和小于k,就直接输出-1。开始模拟打饭,每次我们给全体喂当前打饭人中饭量最少的分量,我们直接从map中取出即可,喂完后,饭量最少的人就离开了队伍,我们要准备一个len来记录队伍剩余的人,以此往复,当剩下的饭不够喂满最低饭量的人时结束循环,我们把剩余饭量k对len取余,这样剩下的饭量就只够再打一趟饭了,我们遍历队伍,如果有没吃饱的人就给他一份饭,然后他把存入另一个数组里(这个数组就充当队尾),要注意,如果有人在此过程中吃饱了,就不存入数组里。最后先输出队伍剩余的人,在输出队尾数组里的人。
(思路来源:https://blog.csdn.net/fnmdpnmsl/article/details/123283788)
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<set>
#include<string>
#include<map>
#include<unordered_map>
#include<stack>
typedef long long ll;
typedef pair<int, int>PII;
int main()
{
map<ll, int>mymap;
ll n, k;
ll sum = 0;
cin >> n >> k;
vector<ll>v(n + 1);
for (int i = 1; i <= n; i++)
{
cin >> v[i];
sum += v[i];
mymap[v[i]]++;
}
if (sum < k)
{
cout << -1 << endl;
return 0;
}
ll len = n, res = 0, algo = 0;
auto it = mymap.begin();
while (it!=mymap.end()&&k >= (it->first - algo) * len)
{
k -= (it->first - algo) * len;
len -= it->second;
res = it->first;
algo = it->first;
it++;
if (len == 1)
cout << " ";
}
if (len == 0)
{
return 0;
}
k %= len;
int ans = 1;
vector<ll>back;
bool flag = false;
for (int i = ans; i <= n && k; i++)
{
flag = false;
if (v[i] == res + 1)
{
k--;
ans = i;
flag = true;
}
else if (v[i] > res)
{
back.push_back(i);
ans = i;
k--;
flag = true;
}
}
if (flag)ans++;
for (int i = ans; i <= n; i++)
{
if (v[i] > res)cout << i << " ";
}
for (int i = 0; i < back.size(); i++)cout << back[i] << " ";
return 0;
}
8、任务分配
思路:
典型的动态规划题。对于每一个任务,只有选或不选两种情况。
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int n,maxi=0;
cin>>n;
int s[1001],e[1001],w[1001];
for(int i=1;i<=n;i++)
{
cin>>s[i]>>e[i]>>w[i];
if(e[i]>maxi)maxi=e[i]; //maxi表示最后一个任务结束的时间
}
int f[1001]={0}; //f[i]表示i时间内能获得的最大收益
for(int i=1;i<=maxi;i++)
{
f[i]=max(f[i],f[i-1]);
for(int j=1;j<=n;j++)
{
if(i==s[j])
{
f[e[j]]=max(f[e[j]],f[i]+w[j]); //选还是不选
}
}
}
cout<<f[maxi];
return 0;
}