結果
| 問題 |
No.5017 Tool-assisted Shooting
|
| コンテスト | |
| ユーザー |
FplusFplusF
|
| 提出日時 | 2025-09-12 21:58:13 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 1,594 ms / 2,000 ms |
| コード長 | 10,700 bytes |
| コンパイル時間 | 3,287 ms |
| コンパイル使用メモリ | 305,812 KB |
| 実行使用メモリ | 26,072 KB |
| スコア | 4,175,764 |
| 平均クエリ数 | 950.00 |
| 最終ジャッジ日時 | 2025-09-12 23:41:18 |
| 合計ジャッジ時間 | 160,205 ms |
|
ジャッジサーバーID (参考情報) |
judge7 / judge3 |
| 純コード判定しない問題か言語 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 100 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
using pii=pair<int,int>;
using tii=tuple<int,int,int>;
using qii=tuple<int,int,int,int>;
using ll=long long;
using ull=unsigned long long;
using ld=long double;
constexpr int INF=1e9;
constexpr ll INF_ll=1e18;
#define rep(i,n) for (int i=0;i<(int)(n);i++)
#define replr(i,l,r) for (int i=(int)(l);i<(int)(r);i++)
#define all(v) v.begin(),v.end()
#define len(v) ((int)v.size())
template<class T> inline bool chmin(T &a,T b){
if(a>b){
a=b;
return true;
}
return false;
}
template<class T> inline bool chmax(T &a,T b){
if(a<b){
a=b;
return true;
}
return false;
}
namespace Timer{
chrono::system_clock::time_point program_start,start;
void program_start_snap(){
program_start=start=chrono::system_clock::now();
}
void snap(){
start=chrono::system_clock::now();
}
int get_ms(){
auto now=chrono::system_clock::now();
int ms=chrono::duration_cast<chrono::milliseconds>(now-start).count();
return ms;
}
int get_ms_all_program(){
auto now=chrono::system_clock::now();
int ms=chrono::duration_cast<chrono::milliseconds>(now-program_start).count();
return ms;
}
}
mt19937 mt;
uint32_t rand_int(uint32_t r){ //[0,r)
assert(r!=0);
return ((uint64_t)mt()*r)>>32;
}
int rand_int(int l,int r){ //[l,r)
assert(l<r);
return l+rand_int(r-l);
}
constexpr double one_div_mt_max=1.0/(double)mt19937::max();
double rand_double(){ //[0.0,1.0]
return mt()*one_div_mt_max;
}
template<class T> T get_random_element(const vector<T> &v){
assert(!v.empty());
return v[rand_int(len(v))];
}
template<class T> void add(vector<T> &a,vector<T> b){
for(auto i:b) a.push_back(i);
}
constexpr int W=25,H=60,T=1000;
namespace Solver{
struct Enemy{
int first_hp,hp,power,end_turn;
Enemy(int h,int p,int turn):first_hp(h),hp(h),power(p),end_turn(turn+H){}
};
using Score=int;
struct Candidate{
int action;
Score score;
int parent;
Candidate(int action_,Score score_,int parent_):action(action_),score(score_),parent(parent_){}
auto operator<=>(const Candidate &other) const{
return this->score<=>other.score;
}
};
struct State{
vector<queue<Enemy>> q;
int pos=12,score=0,level=1,power_sum=0;
int point=0;
vector<int> actions;
int turn=0;
State():q(W){}
auto operator<=>(const State &other) const{
return this->point*this->level<=>other.point*other.level;
}
void add_enemy(int x,int h,int p){
Enemy enemy(h,p,turn);
q[x].push(enemy);
}
Candidate try_advance(int d,int parent) const{
int new_pos=pos+d;
if(new_pos==-1) new_pos=W-1;
if(new_pos==W) new_pos=0;
int new_point=point,new_level=level;
if(!q[new_pos].empty()){
Enemy enemy=q[new_pos].front();
if(enemy.end_turn==turn+1){
return Candidate(d,-INF,parent);
}
enemy.hp-=min(enemy.hp,level);
if(enemy.hp<=0){
new_point+=enemy.first_hp;
new_level=1+(power_sum+enemy.power)/100;
}else{
if(enemy.end_turn==turn+2){
return Candidate(d,-INF,parent);
}
}
}else{
new_point-=10;
if(d==0) new_point-=10;
if(!actions.empty()&&actions.back()+d==0) new_point-=10;
}
rep(w,W){
if(!q[w].empty()){
Enemy enemy=q[w].front();
if(enemy.end_turn!=turn+1){
if(w!=new_pos) new_point-=enemy.first_hp-enemy.hp;
}
}
}
Score new_score=new_point*new_level;
return Candidate(d,new_score,parent);
}
void advance(int d){
pos+=d;
if(pos==-1) pos=W-1;
if(pos==W) pos=0;
actions.push_back(d);
if(!q[pos].empty()){
Enemy &enemy=q[pos].front();
if(enemy.end_turn==turn+1){
//cerr << turn << " " << enemy.first_hp << " " << enemy.hp << " " << enemy.power << " miss" << endl;
score=-INF;
point=-INF;
}
enemy.hp-=min(enemy.hp,level);
if(enemy.hp<=0){
score+=enemy.first_hp;
point+=enemy.first_hp;
power_sum+=enemy.power;
level=1+power_sum/100;
q[pos].pop();
}else{
}
}else{
point-=10;
int sz=len(actions);
if(actions.back()==0) point-=10;
if(2<=sz&&actions[sz-2]+actions[sz-1]==0) point-=10;
}
turn++;
rep(w,W){
if(!q[w].empty()){
Enemy &enemy=q[w].front();
if(enemy.end_turn==turn){
q[w].pop();
}else{
/*int dist=(pos-w+W)%W;
if(!(dist==0||dist==1||dist==W-1)) point-=enemy.first_hp-enemy.hp;*/
if(pos!=w) point-=enemy.first_hp-enemy.hp;
}
}
}
if(!q[pos].empty()){
Enemy &enemy=q[pos].front();
if(enemy.end_turn==turn+1){
//cerr << turn << " " << enemy.first_hp << " " << enemy.hp << " " << enemy.power << " miss" << endl;
score=-INF;
point=-INF;
}
}
}
};
constexpr int Depth=20,Width=5;
vector<int> beam_search(State first_state){
vector<State> dp;
dp.push_back(first_state);
rep(depth,Depth){
//vector<Candidate> candidates;
vector<priority_queue<Candidate,vector<Candidate>,greater<Candidate>>> pq(W);
rep(width,Width){
if(len(dp)<=width) break;
const State &state=dp[width];
replr(d,-1,2){
Candidate candidate=state.try_advance(d,width);
if(candidate.score==-INF) continue;
int pos=state.pos+d;
if(pos==-1) pos=W-1;
if(pos==W) pos=0;
if(!pq[pos].empty()&&candidate<pq[pos].top()) continue;
pq[pos].push(candidate);
if(len(pq[pos])==Width) pq[pos].pop();
}
}
//cerr << "?" << endl;
vector<Candidate> candidates;
rep(pos,W){
while(!pq[pos].empty()){
Candidate candidate=pq[pos].top();
pq[pos].pop();
candidates.push_back(candidate);
//if(len(candidates)==Width) break;
}
}
sort(all(candidates));
reverse(all(candidates));
vector<State> new_dp;
for(auto &candidate:candidates){
State state=dp[candidate.parent];
state.advance(candidate.action);
new_dp.push_back(state);
}
swap(dp,new_dp);
}
if(dp.empty()) return {0};
//cerr << "beam " << dp[0].point << " " << dp[0].level << " " << dp[0].actions[0] << endl;
return dp[0].actions;
}
void solve(){
State state;
rep(_,T){
int n;
cin >> n;
if(n==-1) break;
rep(i,n){
int h,p,x;
cin >> h >> p >> x;
//cerr << h << " " << p << " " << x << endl;
state.add_enemy(x,h,p);
}
state.actions.clear();
int action=beam_search(state)[0];
state.advance(action);
char c='X';
if(action==-1) c='L';
else if(action==0) c='S';
else if(action==1) c='R';
else assert(0);
cout << c << '\n';
cout.flush();
//cerr << state.turn << " ? " << c << endl;
/*if(!state.q[state.pos].empty()){
Enemy enemy=state.q[state.pos].front();
cerr << " !!! " << enemy.end_turn << " " << enemy.hp << endl;
}
cerr << state.turn << " : ";
rep(w,W){
if(!state.q[w].empty()){
cerr << state.q[w].front().end_turn-state.turn << " ";
}else{
cerr << "-1 ";
}
}
cerr << endl;
assert(state.turn<=200);*/
//cerr << len(state.q[state.pos]) << " " << n << " " << state.turn << endl;
//cerr << state.turn << " " << state.score << " " << Timer::get_ms() << endl;
}
cerr << state.score << ' ' << Timer::get_ms_all_program() << '\n';
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
Timer::program_start_snap();
#ifdef LOCAL
rep(i,W){
int _;
cin >> _;
}
#endif
Solver::solve();
exit(0);
}
FplusFplusF