Maximum-Score Ant Solitaire Path
National Olympiad — Regional round (2018 season)
Submission name: solitaire.cpp
Problem summary
Move from bottom-left to top-right in a card grid using only up and right. Maximize collected rank values, including both endpoints.
Input
N, then N rows of N rank-suit cards. Ranks:A,2…9,T,J,Q,K; suits:C,D,H,S.
Output
The maximum path score.
Constraints
1 ≤ N ≤100.
Worked example
Input and output for the worked example discussed below.
Input
4 8S AD 3C AC 8C 4H QD QS 5D 9H KC 7H TC QC AS 2D
Output
69
Solution analysis
- Ignore suits. Convert A to1,T to10,J to11,Q to12,K to13; numeric ranks retain their values.
- A path reaching cell(r,c) comes from below or left. Set dp[r][c]=value[r][c]+max(dp[r+1][c],dp[r][c−1]), processing rows bottom-up and columns left-to-right.
- The sample path TC,QC,9H,KC,QD,QS,AC scores10+12+9+13+12+12+1=69. Positive values make zero-initialized borders safe: a valid predecessor’s score beats an absent predecessor except at the start.
Why it works
Every allowed path uses one of the two enumerated predecessors. Choosing the better optimal predecessor plus the fixed cell value therefore gives the optimum at that cell. The processing order satisfies dependencies, proving the final optimum by induction.
Watch out. Start bottom-left, include both endpoint cards, and map face ranks correctly.
Commented C++17 solution
An independently written complete program with standard headers.
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int rankValue(char rank){
if(rank>='2'&&rank<='9'){
return rank-'0';
}
const string ranks="ATJQK";
const int points[5]={1,10,11,12,13};
return points[ranks.find(rank)];
}
int main(){
int n;
cin>>n;
vector<vector<int>>value(n+2,vector<int>(n+2));
vector<vector<int>>dp(n+2,vector<int>(n+2));
for(int row=1;row<=n;row++){
for(int column=1;column<=n;column++){
string card;
cin>>card;
value[row][column]=rankValue(card[0]);
}
}
for(int row=n;row>=1;row--){
for(int column=1;column<=n;column++){
// Both legal predecessor states have already been processed.
dp[row][column]=value[row][column]+max(dp[row+1][column],dp[row][column-1]);
}
}
cout<<dp[1][n]<<'\n';
}