TopCoder SRM 354 Div1 Easy DateFormat
問題
米国式では日付は月/日と書き、英国式では日付は日/月と書く。
日付のリストが与えられるが、書式がどちらで書かれているか解らない。
日付は、早い順に並んでいるものとするとき、日付を全て米国式で記し、つなげた文字列を返せ。
候補が複数ある場合は辞書順で最小のものを返せ。
制約条件
日付の数≦1000くらい?
方針
dp[pos][i]を、リストのpos番目まで見たとき、現在の日数i日目とすることができるかを持つようなDP+経路復元をした。
よく考えたら、日付を早いほうとして貪欲に使うだけでよかった。
ソースコード
vs date,ans; int n,dp[800][367]; int day[]={0,31,29,31,30,31,30,31,31,30,31,30,31}; int sum[14]; int get(string a){ int m=atoi(a.substr(0,2).c_str()); int d=atoi(a.substr(3).c_str()); if(1<=m&&m<=12&&d<=day[m])return sum[m]+d; return -1; } string rev(string a){ a=a.substr(3)+"/"+a.substr(0,2); return a; } int rec(int pos,int d){ if(pos>=n)return 1; if(dp[pos][d]>=0)return dp[pos][d]; int a=get(date[pos]), b=get(rev(date[pos])); vi v; if(a>=0&&a>d)v.pb(a); if(b>=0&&b>d)v.pb(b); sort(all(v)); dp[pos][d]=0; rep(i,v.size()){ if(rec(pos+1,v[i]))return dp[pos][d]=v[i]; } return 0; } void make(){ ans.clear(); int d=0; rep(i,n){ int nd=dp[i][d]; for(int m=12;;m--)if(sum[m]<nd){ char buf[9]; sprintf(buf,"%02d/%02d",m,nd-sum[m]); ans.pb(buf); break; } d=nd; } } class DateFormat { public: string fromEuropeanToUs(vector <string> dateList) { rep(i,13)sum[i+1]=sum[i]+day[i]; date.clear(); stringstream ss(accumulate(all(dateList),string())); string s; while(ss>>s)date.pb(s); n=date.size(); memset(dp,-1,sizeof(dp)); if(!rec(0,0))return "";; make(); string res=""; rep(i,ans.size())res+=ans[i]+" "; res.erase(res.end()-1); return res; } };