2021.06.26 考试
130=100+20+10(有进步,加油哦~)
1.游戏
【题意描述】
小喵喵喜欢玩RPG游戏。在这款游戏中,玩家有两个属性,攻击和防御,现在小喵喵的攻击和防御都是1,接下来小喵喵会依次遇到n个事件。事件有两种。
1.小喵喵经过修炼,角色升级了,此时可以选择攻击+1或者防御+1.
2.小喵喵遇到了一个敌人,可以选择战斗或者逃跑。如果战斗,胜利后得到a[i]金钱。如果逃跑,则无事发生,但是以后也不能再回来打这个怪物了。
对于一场战斗来说,如果小喵喵的攻击力大于等于atk[i],防御力大于等于def[i],那么他可以无伤打败这只怪物,从而他选择打怪,否则他发现自己会受伤,从而选择逃跑。
现在小喵喵想知道,通过巧妙地选择升级时加的属性,他最多能够从这n个事件中获得多少金钱。
【输入格式】
第1行一个整数n。
第2~n+1行每行会有一个字符’U’或’M’,分别表示升级和怪物,如果是怪物,之后有空格隔开的三个整数a[i],atk[i],def[i]。
【输出格式】
一个整数,表示最多的金钱。
【样例输入输出】
5
U
U
M 2 1 2
M 5 2 1
M 3 1 3 7
【样例解释】
小喵喵可以选择分别增加一次攻击和防御,从而可以打3号和4号怪物。总的金钱是2+5=7.
【数据范围】
对于20%的数据,n<=10
对于另外20%的数据,所有怪物的def[i]为1.
对于另外30%的数据,n<=100
对于所有的数据,n<=2000,1<=atk[i],def[i]<=n,a[i]<=109.
思路:和之前那次地图一样,动态规划,f[i] [j]表示再攻击力为i并且到了第j个关卡时,总金币数最大值。提示:每次攻击力与防御力的值增加1后,必须更新增加后的f[i] [j]的变化
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
const int N=2010;
int n,tot=2,atk[N],def[N],val[N];
ll f[N][N];
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0'){
s=s*10+ch-'0';
ch=getchar();
}
return s*w;
}
int main(){
//freopen("rpg.in","r",stdin);
//freopen("rpg.out","w",stdout);
n=read();
for(int i=1;i<=n;i++){
string s;
cin>>s;
if(s[0]=='U')atk[i]=def[i]=-1;
else{
val[i]=read();atk[i]=read();def[i]=read();
}
}
for(int i=1;i<=n;i++){
if(atk[i]==-1){
++tot;
//cout<<tot<<endl;//
//for(int j=tot-2;j>=1;j--)f[j][i]=max(f[j][i-1],f[j+1][i-1]),cout<<f[j][i]<<" ";
//cout<<endl;
for(int j=1;j<tot;j++)f[j][i]=max(f[j][i-1],f[j-1][i-1]);//,cout<<f[j][i]<<" ";
//cout<<endl<<endl;//
continue;
}
//cout<<tot<<endl;//
for(int j=tot;j>=1;j--){
if(j>=atk[i]&&tot-j>=def[i])f[j][i]=f[j][i-1]+val[i];//,cout<<"1 j "<<j<<" ";
else f[j][i]=f[j][i-1];//,cout<<"2 j "<<j<<" ";
//cout<<f[j][i]<<endl;//
}
//cout<<endl;//
}
ll maxn=0;
for(int i=1;i<tot;i++){
//cout<<f[i][n]<<" ";//
maxn=max(f[i][n],maxn);
}
//cout<<endl<<endl;//
cout<<maxn<<endl;
return 0;
}
// 5 M 2 1 1 U M 1 2 1 M 5 1 2 M 4 2 2
// 7 M 2 1 1 M 6 1 2 U M 7 2 1 M 3 1 2 U M 9 3 1
2.上学
【题意描述】
小喵喵家附近有n个路口,m条道路连接着这些路口,而且通过这些道路各自需要一些时间c[i]。小喵喵在1号路口,他要去n号路口上学,但是他马上要迟到了,所以他想知道最短需要多长时间能够到达学校。其中忽略小喵喵由于出家门、到n号路口之后进入学校、从一条道路移动到另一条道路之类的时间,只计算他在这些道路上花费的时间总和。
除此之外,小喵喵还有k个时间暂停器,每个可以使某一条道路的经过时间变为0.
【输入格式】
第1行三个整数n,m,k,表示路口个数,道路的数量,时间暂停器的数量。
第2~m+1行每行三个整数u[i],v[i],c[i],表示u[i]和v[i]之间有一条可以双向通行的道路,通过所需时间为c[i]。
【输出格式】
一个整数,表示小喵喵所需的最短时间。
【样例输入输出】
5 6 1
1 2 2
1 3 4
2 4 3
3 4 1
3 5 6
4 5 2 3
【样例解释】
小喵喵选择从1->3->4->5,并且在1->3的道路上使用时间暂停器。
总耗时为0+1+2=3.
【数据范围】
对于20%的数据,n<=5,m<=10.
对于另外20%的数据,k=0.
对于另外30%的数据,k=1.
对于所有的数据,n<=1000,m<=10000,k<=10,c[i]<=109,保证存在从1号路口到n号路口的路径。注意,可能存在两条道路的起点和终点组成的集合相同,也可能存在起点和终点是相同路口的道路。
思路:分层图,共建k+1层,分别比对每一层终点的最小值
代码来自网上不知道具体是谁的老师的
#include <iostream>
#include <queue>
using namespace std;
struct Node{
int v, w;
Node(){}
Node(int av, int aw): v(av), w(aw){}
bool operator < (const Node& b) const {
return w > b.w;
}
}node;
vector<vector<Node> > g;
queue<Node> q;
vector<long long> dist, uptimes;
const long long INF = (long long)1 << 62;
int n, m, k, u, v, w;
bool spfa() {
q.push(Node(1+k*n, 0)); dist[1+k*n] = 0;
while (q.size()) {
node = q.front(), q.pop();
for (int i = 0, j = g[node.v].size(); i < j; ++i) {
Node tN = g[node.v][i];
if (dist[tN.v] > dist[node.v] + tN.w) {
dist[tN.v] = dist[node.v] + tN.w, q.push(Node(tN.v, node.w+tN.w));
if(++uptimes[tN.v] >= n) return false;
}
}
}
return true;
}
int main() {
ios::sync_with_stdio(false);
cin >> n >> m >> k;
g.resize(m*(k+2)); dist.resize(m*(k+2)); uptimes.resize(m*(k+2));
fill(dist.begin(), dist.end(), INF);
for (int i = 1; i <= m; ++i) {
cin >> u >> v >> w;
//使用多层图,将动态规划的各个状态以不同层列出,0边在不同层之间连接,从而避免了重边
for (int j = 0; j <= k; ++j) {
g[u+j*n].push_back(Node(v+j*n, w));
g[v+j*n].push_back(Node(u+j*n, w));
if (j) {
g[u+j*n].push_back(Node(v+(j-1)*n, 0));
g[v+j*n].push_back(Node(u+(j-1)*n, 0));
}
}
}
spfa();
long long minN = INF;
for (int i = 0; i <= k; ++i)
minN = min(minN, dist[n+i*n]);
cout << minN << endl;
return 0;
}
3.数数
【题意描述】
定义一个数列的代价如下:
每次操作可以选择一个区间,和一个 2 的幂次,使得这个区间的 所有数字减去这个 2 的幂次。最少的使得这个数列全部减为 0 的操作 次数即为这个数列的代价。注意在减的时候要求二进制下这个区间的 所有数字都要是 1,即在二进制下,这个减法不能退位。
例如:5 2 2 中,不能进行[1,3]减去 2 的操作,因为(5)10=(101)2, 在第二位不是 1,所以不能减。
又如:7 5 3 数列的代价为 4,可以进行如下操作:[1,3]减 1, [1,2]减 4,[1,1]减 2,[3,3]减 2.
小喵喵有一个长度为 n 的数列 a[i]。他想知道 a[i]的所有 子序列(可以是不连续的)的代价之和。因为这个数字可能非常 大,你只需要输出 ans%998244353 的结果就可以了。
【输入格式】
第 1 行一个整数 n。 第二行 n 个用空格隔开的整数 a[i]。
【输出格式】
一个整数,表示 a[i]的所有子序列的代价之和对 998244353 取 模的结果。
【样例输入输出】
3
7 5 3
20
思路无,这一题还不会,等我什么时候会了,什么时候写,先留个坑
posted on
浙公网安备 33010602011771号