#include using namespace std; const int N = 256; const int PARTIES = 1<<17; const double TIME_LIMIT = 4.50; int n,p,k,a[N][N]; pair < int, int > starting_position; pair < int, int > party_position[PARTIES]; pair < int, int > party_time[PARTIES]; pair < int, int > cake_position[N]; bool has_cake[N][N]; priority_queue < pair < int, int >, vector < pair < int, int > >, greater < pair < int, int > > > q[N][N]; long long ans; string path; namespace tools { struct xorshift { unsigned x,y,z,w; xorshift(): x(123456789), y(837983), z(7777777), w(37832) {} unsigned next() { unsigned t=x^(x<<11); x=y;y=z;z=w; return w=w^(w>>19)^t^(t>>8); } unsigned next(unsigned a) { return next()%a; } unsigned next(unsigned a, unsigned b) { return a+next(b-a+1); } }; int bits_count(int n) { int ans=0; while(n) ans+=(n&1),n>>=1; return ans; } template < class T > void random_shuffle(T *a, int from, int to, xorshift rng) { int i; for(i=from+1;i<=to;i++) swap(a[i],a[rng.next(from,i-1)]); } void concatenate(string &a, string b) { int i; for(i=0;i<(int)(b.size());i++) a.push_back(b[i]); } string convert(long long a) { string ans; while(a) ans.push_back(a%10+'0'),a/=10; reverse(ans.begin(),ans.end()); return ans; } long long get_cost(pair < int, int > from, pair < int, int > to, long long cakes) { return (abs(a[from.first][from.second]-a[to.first][to.second])+cakes)*(abs(a[from.first][from.second]-a[to.first][to.second])+cakes)+1; } pair < string, long long > get_path(pair < int, int > from, pair < int, int > to, long long cakes) { string ans; long long cost=0; while(from.firstto.first) { cost+=get_cost(from,make_pair(from.first-1,from.second),cakes); --from.first; ans.push_back('U'); //if(has_cake[from.first][from.second]) ans.push_back('+'); } while(from.secondto.second) { cost+=get_cost(from,make_pair(from.first,from.second-1),cakes); --from.second; ans.push_back('L'); //if(has_cake[from.first][from.second]) ans.push_back('+'); } return make_pair(ans,cost); } void combine(pair < string, long long > &a, pair < string, long long > b) { a.second+=b.second; concatenate(a.first,b.first); } bool time_is_ok() { return (clock()<=TIME_LIMIT*CLOCKS_PER_SEC); } }; namespace closest_party_cake_greedy { int CAKES=0; string path; long long ans; pair < int, int > current_position; long long time_elapsed; long long best[1<<17]; int who_is[1<<17]; void initialize() { int i; current_position=starting_position; ans=0; path.clear(); time_elapsed=0; } void run() { long long cost,min_cost,curr; long long arriving_time; pair < string, long long > current_path; int who; int i,j; initialize(); while(tools::time_is_ok()) { min_cost=numeric_limits < long long >::max(); for(i=1;i<=p && tools::time_is_ok();i++) { best[i]=numeric_limits < long long >::max(); for(j=1;j<=k && tools::time_is_ok();j++) { curr=time_elapsed+tools::get_path(current_position,cake_position[j],0).second+tools::get_path(cake_position[j],party_position[i],CAKES).second; //printf("%lld\n", curr); if(curr::max()) break; //printf("%d %lld\n", who, min_cost); current_path=tools::get_path(current_position,cake_position[j],0); tools::concatenate(current_path.first,tools::convert(CAKES)); current_path=tools::combine(current_path,tools::get_path(cake_position[j],party_position[i],CAKES)); //ans+=current_path.second; ans+=(party_time[who].second-max(party_time[who].first+0ll,time_elapsed+current_path.second))*(CAKES+1); tools::concatenate(path,current_path.first); tools::concatenate(path,tools::convert(CAKES)); current_position=party_position[who]; time_elapsed=party_time[who].second;*/ //printf("%s\n", path.c_str()); if(min_cost==numeric_limits < long long >::max()) break; current_path=tools::get_path(current_position,cake_position[who_is[who]],0); tools::concatenate(current_path.first,tools::convert(CAKES)); tools::combine(current_path,tools::get_path(cake_position[who_is[who]],party_position[who],CAKES)); arriving_time=best[who]; while(!q[party_position[who].first][party_position[who].second].empty() && q[party_position[who].first][party_position[who].second].top().second current_position; long long time_elapsed; long long best[1<<17]; int who_is[1<<17]; void initialize() { int i; current_position=starting_position; ans=0; path.clear(); time_elapsed=0; } void run() { long long cost,min_cost,curr; long long arriving_time; pair < string, long long > current_path; int who; int i,j; initialize(); while(tools::time_is_ok()) { min_cost=numeric_limits < long long >::max(); for(i=1;i<=p && tools::time_is_ok();i++) { best[i]=numeric_limits < long long >::max(); for(j=1;j<=k && tools::time_is_ok();j++) { curr=time_elapsed+tools::get_path(current_position,cake_position[j],0).second+tools::get_path(cake_position[j],party_position[i],CAKES).second; //printf("%lld\n", curr); if(curr::max() && party_time[i].second::max()) break; //printf("%d %lld\n", who, min_cost); current_path=tools::get_path(current_position,cake_position[j],0); tools::concatenate(current_path.first,tools::convert(CAKES)); current_path=tools::combine(current_path,tools::get_path(cake_position[j],party_position[i],CAKES)); //ans+=current_path.second; ans+=(party_time[who].second-max(party_time[who].first+0ll,time_elapsed+current_path.second))*(CAKES+1); tools::concatenate(path,current_path.first); tools::concatenate(path,tools::convert(CAKES)); current_position=party_position[who]; time_elapsed=party_time[who].second;*/ //printf("%s\n", path.c_str()); if(min_cost==numeric_limits < long long >::max()) break; current_path=tools::get_path(current_position,cake_position[who_is[who]],0); tools::concatenate(current_path.first,tools::convert(CAKES)); tools::combine(current_path,tools::get_path(cake_position[who_is[who]],party_position[who],CAKES)); arriving_time=best[who]; while(!q[party_position[who].first][party_position[who].second].empty() && q[party_position[who].first][party_position[who].second].top().second current_position; long long time_elapsed; long long best[1<<17]; int who_is[1<<17]; void initialize() { int i; current_position=starting_position; ans=0; path.clear(); time_elapsed=0; } void run() { long long cost,min_cost,curr; long long arriving_time; pair < string, long long > current_path; int who; int i,j; initialize(); while(tools::time_is_ok()) { min_cost=numeric_limits < long long >::max(); for(i=1;i<=p && tools::time_is_ok();i++) { best[i]=numeric_limits < long long >::max(); for(j=1;j<=k && tools::time_is_ok();j++) { curr=time_elapsed+tools::get_path(current_position,cake_position[j],0).second+tools::get_path(cake_position[j],party_position[i],CAKES).second; //printf("%lld\n", curr); if(curr::max() && party_time[i].first::max()) break; //printf("%d %lld\n", who, min_cost); current_path=tools::get_path(current_position,cake_position[j],0); tools::concatenate(current_path.first,tools::convert(CAKES)); current_path=tools::combine(current_path,tools::get_path(cake_position[j],party_position[i],CAKES)); //ans+=current_path.second; ans+=(party_time[who].second-max(party_time[who].first+0ll,time_elapsed+current_path.second))*(CAKES+1); tools::concatenate(path,current_path.first); tools::concatenate(path,tools::convert(CAKES)); current_position=party_position[who]; time_elapsed=party_time[who].second;*/ //printf("%s\n", path.c_str()); if(min_cost==numeric_limits < long long >::max()) break; current_path=tools::get_path(current_position,cake_position[who_is[who]],0); tools::concatenate(current_path.first,tools::convert(CAKES)); tools::combine(current_path,tools::get_path(cake_position[who_is[who]],party_position[who],CAKES)); arriving_time=best[who]; while(!q[party_position[who].first][party_position[who].second].empty() && q[party_position[who].first][party_position[who].second].top().second current_position=starting_position; pair < string, int > current_path; long long time_elapsed=0; int i; ans=0; path.clear(); for(i=1;i<=p;i++) { current_path=tools::get_path(starting_position,party_position[parties[i]],0); if(current_path.second+time_elapsed<=party_time[parties[i]].second) { arriving_time=current_path.second+time_elapsed; while(!q[party_position[parties[i]].first][party_position[parties[i]].second].empty() && q[party_position[parties[i]].first][party_position[parties[i]].second].top().secondans) ans=current_ans,path=current_path; if(p==1) return; for(i=1;i<=MOVES && tools::time_is_ok();i++) { for(j=1;j<=p;j++) while(!q[party_position[j].first][party_position[j].second].empty()) q[party_position[j].first][party_position[j].second].pop(); for(j=1;j<=p;j++) q[party_position[j].first][party_position[j].second].push(party_time[j]); j=rng.next(1,p-1); swap(parties[j],parties[j+1]); evaluate(current_ans,current_path); if(current_ans>ans) ans=current_ans,path=current_path; } } }; namespace yes_cakes_2opt { int CAKES = 0; const int MOVES = 100; int parties[PARTIES]; tools::xorshift rng; long long ans; string path; string current_path; long long arriving_time; long long current_ans; void evaluate(long long &ans, string &path) { pair < int, int > current_position=starting_position; pair < string, int > current_path; long long time_elapsed=0; int i; ans=0; path.clear(); for(i=1;i<=p;i++) { current_path=tools::get_path(starting_position,party_position[parties[i]],0); if(current_path.second+time_elapsed<=party_time[parties[i]].second) { arriving_time=current_path.second+time_elapsed; while(!q[party_position[parties[i]].first][party_position[parties[i]].second].empty() && q[party_position[parties[i]].first][party_position[parties[i]].second].top().secondans) ans=current_ans,path=current_path; if(p==1) return; for(i=1;i<=MOVES && tools::time_is_ok();i++) { for(j=1;j<=p;j++) while(!q[party_position[j].first][party_position[j].second].empty()) q[party_position[j].first][party_position[j].second].pop(); for(j=1;j<=p;j++) q[party_position[j].first][party_position[j].second].push(party_time[j]); j=rng.next(1,p-1); swap(parties[j],parties[j+1]); evaluate(current_ans,current_path); if(current_ans>ans) ans=current_ans,path=current_path; } } }; int main() { freopen("party.in","r",stdin); freopen("party.out","w",stdout); int i,j; scanf("%d %d %d", &n, &p, &k); for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { scanf("%d", &a[i][j]); } } scanf("%d %d", &starting_position.first, &starting_position.second); //printf("Here\n"); for(i=1;i<=p;i++) scanf("%d %d %d %d", &party_position[i].first, &party_position[i].second, &party_time[i].first, &party_time[i].second),party_time[i].second+=party_time[i].first; for(i=1;i<=k;i++) scanf("%d %d", &cake_position[i].first, &cake_position[i].second),has_cake[cake_position[i].first][cake_position[i].second]=true; //for(i=1;i<=p;i++) q[party_position[i].first][party_position[i].second].push(party_time[i]); //no_cakes_2opt::run(); //if(no_cakes_2opt::ans>ans) ans=no_cakes_2opt::ans,path=no_cakes_2opt::path; //printf("Here\n"); while(tools::time_is_ok()) { //printf("Here\n"); for(i=1;i<=p;i++) while(!q[party_position[i].first][party_position[i].second].empty()) q[party_position[i].first][party_position[i].second].pop(); for(i=1;i<=p;i++) q[party_position[i].first][party_position[i].second].push(party_time[i]); ++closest_party_cake_greedy::CAKES; closest_party_cake_greedy::run(); if(closest_party_cake_greedy::ans>ans) ans=closest_party_cake_greedy::ans,path=closest_party_cake_greedy::path; /*++first_ending_greedy::CAKES; first_ending_greedy::run(); if(first_ending_greedy::ans>ans) ans=first_ending_greedy::ans,path=first_ending_greedy::path; ++first_starting_greedy::CAKES; first_starting_greedy::run(); if(first_starting_greedy::ans>ans) ans=first_starting_greedy::ans,path=first_starting_greedy::path;*/ //++yes_cakes_2opt::CAKES; //yes_cakes_2opt::run(); //if(yes_cakes_2opt::ans>ans) ans=yes_cakes_2opt::ans,path=yes_cakes_2opt::path; } printf("%s\n", path.c_str()); fprintf(stderr, "Score: %lld\n", ans); return 0; }