PKU 3516 Johnny Hates Math
http://poj.org/problem?id=3516
数字=数字という式の左辺に+を入れて等式が成り立つようにしろというような問題。
ただし、数字は全て正数で最上位桁は0でない。
また、候補が複数ある場合は+の個数が最小になるものを出力すること。
+の個数の条件を見落としていてWAの原因に頭を悩ませました。
set
DP+経路復元っぽい問題でした。
string in; typedef struct _node{ int a,b; int c; _node* next; }node; const int hashMod=300000; node* hash[hashMod]; node ent[10000000]; int sz; void insert(int a,int b,int c){ int ha=(a*31+b)%hashMod; node* p=ent+sz++; p->a=a; p->b=b; p->c=c; p->next=hash[ha]; hash[ha]=p; } node* app(int a,int b){ int ha=(a*31+b)%hashMod; for(node* p=hash[ha];p;p=p->next) if(p->a==a && p->b==b)return p; return NULL; } int rec(int p,int nu){ if(p==0 && nu==0)return 0; if(nu<=0)return -1; { node* re=app(p,nu); if(re)return re->c; } int ret=-1; int base=1; int re=0; for(int i=0;i<5;++i){ if(p-i-1<0)break; re+=base*(in[p-i-1]-'0'); base*=10; if(in[p-i-1]=='0')continue; int tre=rec(p-i-1,nu-re); if(tre>=0){ if(ret==-1)ret=tre+1; ret=min(ret,tre+1); } } insert(p,nu,ret); return ret; } void getpath(int p,int nu){ if(p==0 && nu==0)return; int base=1; int re=0; int ret=app(p,nu)->c; for(int i=0;i<5;++i){ re+=base*(in[p-i-1]-'0'); base*=10; if(in[p-i-1]=='0')continue; if(rec(p-i-1,nu-re)+1==ret){ getpath(p-i-1,nu-re); if(nu-re) cout<<'+'; cout<<re; return; } } } void solve(int n){ printf("%d. ",n); memset(hash,0,sizeof(hash)); sz=0; int re=0; for(int i=in.find('=')+1;i<SZ(in);++i) re=re*10+in[i]-'0'; if(rec(in.find('='),re)>=0){ getpath(in.find('='),re); cout<<in.substr(in.find('='))<<endl; }else puts("IMPOSSIBLE"); } main(){ int te=0; while(cin>>in,in!="0=0") solve(++te); }