洛谷 P8874 [传智杯 #5 初赛] F-二人的大富翁游戏
题目链接
大模拟,模拟就完事了
数组的解释
题目中的坐标为1到n,为了方便取模操作我们使用0到n-1
c
[
i
]
[
j
]
c[i][j]
c[i][j]表示位于位置
i
i
i的建筑物从
j
−
1
j-1
j−1升级到
j
j
j的花费
s
[
i
]
[
j
]
s[i][j]
s[i][j]表示位于位置
i
i
i的建筑物从
0
0
0升级到
j
j
j的花费
d
[
i
]
d[i]
d[i]表示位于位置
i
i
i的建筑物回合末提供给拥有者的资金
s
t
[
i
]
st[i]
st[i]表示位于位置
i
i
i的建筑物的拥有者
其中
s
t
[
i
]
=
1
st[i]=1
st[i]=1表示建筑物
i
i
i被莲子占有,
s
t
[
i
]
=
2
st[i]=2
st[i]=2表示建筑物
i
i
i被梅莉占有
l
e
v
e
l
[
i
]
level[i]
level[i]表示建筑物
i
i
i的等级
c
u
r
=
1
/
2
cur=1/2
cur=1/2表示当前轮到莲子/梅莉
p
o
s
[
1
/
2
]
pos[1/2]
pos[1/2]表示莲子/梅莉的坐标
m
o
n
e
y
[
1
/
2
]
money[1/2]
money[1/2]表示莲子/梅莉的钱
s [ i ] [ j ] s[i][j] s[i][j]可由前缀和求得 s [ i ] [ j ] = s [ i ] [ j − 1 ] + c [ i ] [ j ] s[i][j]=s[i][j-1]+c[i][j] s[i][j]=s[i][j−1]+c[i][j]
操作过程
在读入操作序列的时候需要注意读入操作
当op=1时
- 当读入两次op=1时表示,一个回合结束,应将每个人占有的建筑物的收益加上
- 转换当前进行移动的人,这里使用
c
u
r
=
c
u
r
%
2
+
1
cur=cur\%2+1
cur=cur%2+1进行转换(或者
c
u
r
=
3
−
c
u
r
cur=3-cur
cur=3−cur也是可以的)
- c u r = 1 cur=1 cur=1时 c u r % 2 + 1 = 2 cur\%2+1=2 cur%2+1=2
- c u r = 2 cur=2 cur=2时 c u r % 2 + 1 = 1 cur\%2+1=1 cur%2+1=1
- 这里要注意前进的时候注意做取模操作,从起点到终点的每一步都需要做判断建筑物带给自己的损失和收益。
当op=2时
- 判断当前建筑物是否是自己的或者未占有的,将建筑物提升到可以提升到的最大等级
- 将 s t [ ] st[] st[]数组标记为自己,需要注意的一点,当建筑物至少提升1级时,才可以将建筑物标记
第一次写题解,还有许多不足,希望大家多多指教 ⌣ \smile ⌣
#include <iostream>
#include <vector>
using namespace std;
#define int long long
typedef pair<int,int> PII;
const int MAXN=100+10;
int c[MAXN][MAXN];
int s[MAXN][MAXN];
int d[MAXN];
int st[MAXN];
int level[MAXN];
signed main()
{
int n,m,q,L;
cin>>n>>m>>q>>L;
for(int i=0;i<n;i++)
{
for(int j=1;j<=L;j++)
{
cin>>c[i][j];
s[i][j]=s[i][j-1]+c[i][j];
}
}
for(int i=0;i<n;i++)
{
cin>>d[i];
}
vector<PII> seq;
int op,x;
while(cin>>op>>x)
{
if(op==0)
break;
seq.push_back({op,x});
}
int cur=1;
int pos[3]={0,0,0};
int money[3]={m,m,m};
bool lose[3]={0,0,0};
int cnt=0;
for(int i=0;i<seq.size();i++)
{
int op=seq[i].first;
if(op==1)
{
if(cnt%2==0)
{
for(int t=0;t<n;t++)
{
if(st[t]!=0)
{
money[st[t]]+=d[t];
}
}
}
cnt++;
if(i>0)
cur=cur%2+1;
int k=seq[i].second;
int current_pos=pos[cur];
for(int i=0;i<k;i++)
{
current_pos=(current_pos+1)%n;
if(st[current_pos]==0)
continue;
else if(st[current_pos]!=cur)
{
money[cur]-=s[current_pos][level[current_pos]];
money[cur%2+1]+=s[current_pos][level[current_pos]];
}
else if(st[current_pos]==cur)
{
money[cur]+=s[current_pos][level[current_pos]];
}
if(money[cur]<0)
{
if(cur==1)
cout<<"Renko\n";
else if(cur==2)
cout<<"Merry\n";
return 0;
}
}
pos[cur]=(pos[cur]+k)%n;
}
else if(op==2)
{
int k=seq[i].second;
int current_pos=pos[cur];
if(st[current_pos]==cur||st[current_pos]==0)
{
int current_level=level[current_pos];
int want_level=min(L,current_level+k);
for(int i=want_level;i>current_level;i--)
{
int cost=s[current_pos][i]-s[current_pos][current_level];
if(money[cur]>=cost)
{
money[cur]-=cost;
st[current_pos]=cur;
level[current_pos]=i;
break;
}
}
}
}
}
for(int t=0;t<n;t++)
{
if(st[t]!=0)
{
money[st[t]]+=d[t];
}
}
cout<<money[1]<<' '<<money[2]<<'\n';
return 0;
}