目录
第一题:特殊的正方形
思路
一道模拟题,主要理清正方形收缩的过程,思路不难,不过多的赘述
代码
#include<bits/stdc++.h>
using namespace std;
char mp[105][105];
char choice[] = { '+','.' };
int main()
{
int n; cin >> n;
int left = 1, right = n;
int dis = n;
while (dis>=0)
{
char c = choice[(left+1) % 2];
for (int i = 0; i < dis; i++)
{
mp[left + i][left] = c;
mp[left + i][right] = c;
mp[left][left + i] = c;
mp[right][left + i] = c;
}
right--, left++;
dis -= 2;
}
for (int i = 1; i <= n; i++)
{
for(int j=1;j<=n;j++)
{
cout << mp[i][j];
}
cout << endl;
}
return 0;
}
第二题:走楼梯2
思路
与正常的走楼梯不同它限制了连续走俩次的次数,而此时可以设f[i][j]来表示最后三次迈步到j,其中三次中有i个连续的第二步,则此时的状态转移方程为
f[0][j]=f[0][j-1]+f[1][j-1]+f[2][j-1];
f[1][j]=f[0][j-2];
f[2][j]=f[1][j-2];
代码
#include<bits/stdc++.h>
using namespace std;
long long f[3][55];
int main()
{
int n, ans = 1;
cin >> n;
f[0][1] = 1, f[1][1] = 0, f[2][1] = 0;
f[0][2] = 1, f[1][2] = 1, f[2][2] = 0;
f[0][3] = 2, f[1][3] = 1, f[2][3] = 0;
f[0][4] = 3, f[1][4] = 1, f[2][4] = 1;
for (int i = 5; i <= n; i++)
{
f[0][i] = f[0][i - 1] + f[1][i - 1] + f[2][i - 1];
f[1][i] = f[0][i - 2];
f[2][i] = f[1][i - 2];
}
cout << f[0][n] + f[1][n] + f[2][n];
return 0;
}
第三题:走路
思路
又是一道动态规划的题目,不妨设f[i][j]表示第i步时第j个位置上能否走到,则很容易知道状态转移方程为f[i][j]=f[i-1][j-a[i]]+f[i-1][j-b[i]],表示第i步的第j个位置可以分别由第i-1步的j-a和j-b的位置上到达
代码
#include<bits/stdc++.h>
using namespace std;
bool vis[105][100050];
int main()
{
int n, m,a,b;
cin >> n >> m;
cin >> a >> b;
vis[0][0] = 1;
vis[1][a] = vis[1][b]=1;
for (int i = 2; i <= n; i++)
{
cin >> a >> b;
if (a > b)swap(a, b);
for (int j = m; j >= a; j--)
{
vis[i][j] += vis[i - 1][j - a];
if (j >= b)
{
vis[i][j] += vis[i - 1][j - b];
}
}
}
for (int i = 0; i <= m; i++)
{
if (vis[n][i])cout << "1";
else
{
cout << "0";
}
}
return 0;
}
第四题:简单的分数统计
思路
一道很简单的模拟题,可以利用pair<string ,int >来储存题目和对应的分数,后面就很简单了,直接就上代码
代码
#include<bits/stdc++.h>
using namespace std;
string a[205];
pair<string, int >b[205];
long long ans[205];
int main()
{
int n, m, k;
cin >> n >> m >> k;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
for (int i = 1; i <= m; i++)
{
cin >> b[i].first >> b[i].second;
}
for(int i=1;i<=k;i++)
{
string x, y, z;
cin >> x >> y >> z;
int c=0;
for (int j = 1; j <= n; j++)
{
if (a[j] == x)
{
c = j;
break;
}
}
if(c!=0)
{
int now=0;
for(int j=1;j<=m;j++)
{
if (y == b[j].first)
{
now = j;
break;
}
}
if (z == "AC")
{
ans[c] += b[now].second;
}
}
}
for (int i = 1; i <= n; i++)
{
cout << a[i] << " " << ans[i] << endl;
}
return 0;
}
第五题:Alice的德州扑克
原题链接Alice的德州扑克
思路
一道比较简单的模拟题,只要分析清楚每种牌型的大小就好了
代码
#include<bits/stdc++.h>
using namespace std;
int a[6], b[6],cnt[15];
int main()
{
bool flag = 1,flag_A=1,flag_B=0,flag_C=0,flag_D=0;
int x;
for (int i = 1; i <= 5; i++)
{
cin >> a[i];
cnt[a[i]]++;
if (i != 1)
{
if (a[i] != a[i - 1] + 1)
{
flag_A = 0;
}
}
}
for (int i = 1; i <= 5; i++)
{
cin >> b[i];
x = b[1];
if (i != 1)
{
if (x != b[i])
{
flag = 0;//表示不是同花
}
}
}
for (int i = 1; i <= 15; i++)
{
if (cnt[i] == 4)
{
flag_B = 1;
}
if (cnt[i] == 3)
{
flag_C = 1;
}
if (cnt[i] == 2)
{
flag_D = 1;
}
}
if (a[1] = 10 && a[2] == 11&&a[3]==12&&a[4]==13&&a[5]==14&&flag)
{
cout << "ROYAL FLUSH" << endl;
}
else if (flag_A&&flag)
{
cout << "STRAIGHT FLUSH" << endl;
}
else if (flag_B)
{
cout << "FOUR OF A KIND" << endl;
}
else if (flag_C&&flag_D)
{
cout << "FULL HOUSE" << endl;
}
else if (flag)
{
cout << "FLUSH" << endl;
}
else if (flag_A)
{
cout << "STRAIGHT" << endl;
}
else
{
cout << "FOLD" << endl;
}
return 0;
}
第六题:订单编号
思路
- 设立一个存放区间的 set,按照右端点大小来排序
- 按照顺序重新定下编号,对于原来编号 x,找区间 [L,R],R 应当在大于等于 x的情况下尽可能小
- 给这个订单定一个新编号 max(L,x)并将这个区间进行拆分,随后再 insert 进去
代码
#include<bits/stdc++.h>
using namespace std;
set<pair<int, int> > s;
void insert(int L, int R) {
if (L > R) return;
s.insert(make_pair(R, L));
}
int main()
{
insert(1, 2e9);
int n;
cin >> n;
for (int i = 1, x; i <= n; ++i) {
cin >> x;
auto it = s.lower_bound(make_pair(x, 0));
int res = max(x, it->second);
insert(it->second, res - 1);
insert(res + 1, it->first);
cout << res << " ";
s.erase(it);
}
return 0;
}
第七题:饿饿 饭饭
思路
可以利用二分答案,看可以求出完整打完全部的次数,然后再通过模拟得到答案
代码
#include<bits/stdc++.h>
using namespace std;
#define LL long long
LL n, K, sum;
int a[100050];
LL res;
vector<int >v;
LL check(LL mid)
{
res = 0;
for (int i = 1; i <= n; i++)
{
if (a[i] <= mid)
{
res += a[i];
}
else
{
res += mid;
}
}
return res;
}
int main()
{
cin >> n >> K;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
sum += a[i];
}
if (sum < K)
{
cout << "-1" << endl;
}
else
{
LL L = 0, R = 1000000000, mid, ans;
while (L < R)
{
mid = (L + R) / 2;
if (check(mid) <= K)
{
L = mid+1;
}
else
{
R = mid-1;
}
}
int x = K - check(L);
for (int i = 1; i <= n; i++)
{
if (a[i] > L)
{
v.push_back(i);
}
}
for (int i = x; i < v.size(); i++)
{
cout << v[i] << " ";
}
for (int i = 0; i < x; i++)
{
if (a[v[i]] != L + 1)
{
cout << v[i] << " ";
}
}
}
return 0;
}
第八题:任务分配
思路
这道题与之类似的是(92条消息) 第三次双周赛_Serendipity_AC的博客-CSDN博客
中的第三题会议安排,不同的是一个是贪心算法,能去则去,而这道题则是动态规划,
用f[i]表示i时间时所获得的最大收益,可以知道有俩种情况,一是不参加任务,即中途没有任务安排,则f[i]=f[i-1],第二种是参加任务,则当i==ed[j]即表示当前时间是一个任务的结束时间,这时候就有俩种选择一是回到st[i]去参加工作,二是不参加,即为f[i]=max(f[st[i]]+w[i],f[i]).
代码
#include<bits/stdc++.h>
using namespace std;
int a[1005], b[1005], w[1005];
long long f[1005];
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i] >> b[i] >> w[i];
}
for (int i = 1; i <= 1000; i++)
{
f[i] = max(f[i], f[i - 1]);
for(int j=1;j<=n;j++)
{
if (i == b[j])
{
f[i] = max(f[a[j]] + w[j], f[i]);
}
}
}
cout << f[1000] << endl;
return 0;
}