バレンタインのカンニング
自分との共通項が0でもなぜかロマンチストになってしまうバレンタインデー、自力で解けた問題少ない。
頭悪すぎて生きてる意味がない。
3615
ある点からある点に行く時に通る辺の最大コストが最小になるような行き方を求める問題。
ある点iからある点jの答えはある点kを通過するかしないかというのはワーシャルフロイドと同じ考え方で、つまりiからkまでの最大コストとkからjまでの最大コストの大きい方がiからjまでの最大コストになる。
だからワーシャルフロイドの足し算の項をmax()に置き換えればいい。
#include <cstdio> #include <climits> #include <algorithm> using namespace std; const int INF=INT_MAX/2; int n, m, t; int d[300][300]; int main() { for (int i=0; i<300; i++) for (int j=0; j<300; j++) d[i][j]=INF; scanf("%d%d%d",&n,&m,&t); for (int i=0; i<m; i++) { int s, e, h; scanf("%d%d%d",&s,&e,&h); d[s-1][e-1]=h; } for (int k=0; k<n; k++) { for (int i=0; i<n; i++) { for (int j=0; j<n; j++) d[i][j]=min(d[i][j],max(d[i][k],d[k][j])); } } for (int i=0; i<t; i++) { int a,b;scanf("%d%d",&a,&b); if (d[a-1][b-1]==INF) puts("-1"); else printf("%d\n",d[a-1][b-1]); } }
1182
Union-Find木蟻本例題。
結局終始蟻本だよりだった気がする(^_^;)
でも要するにただの論理です。
#include <cstdio> struct unionfind { int par[150001], rank[150001]; unionfind(int n) { for (int i=0; i<n; i++) { par[i]=i; rank[i]=0; } } int find(int x) { if (par[x]==x) { return x; } else { return par[x]=find(par[x]); } } void unite(int x, int y) { x=find(x); y=find(y); if (x==y) return; if (rank[x]<rank[y]) { par[x]=y; } else { par[y]=x; if (rank[x]==rank[y]) rank[x]++; } } bool same(int x, int y) { return find(x)==find(y); } }; int n, k; int main() { scanf("%d%d",&n,&k); unionfind uf(3*n); int res=0; for (int i=0; i<k; i++) { int t,x,y; scanf("%d%d%d",&t,&x,&y); x--; y--; if (x<0||n<=x||y<0||n<=y) { res++; continue; } if (t==1) { if (uf.same(x,y+n)||uf.same(x,y+2*n)) { res++; } else { uf.unite(x,y); uf.unite(x+n,y+n); uf.unite(x+2*n,y+2*n); } } else { if (uf.same(x,y)||uf.same(x,y+2*n)) { res++; } else { uf.unite(x,y+n); uf.unite(x+n,y+2*n); uf.unite(x+2*n,y); } } } printf("%d\n",res); }
3723
またもや蟻本。。。
日本語文見ても解法みるまで題意がわからなかったwww
#include <cstdio> #include <algorithm> using namespace std; typedef long long ll; struct unionfind { int par[20001], rank[20001]; unionfind(int n) { for (int i=0; i<n; i++) { par[i]=i; rank[i]=0; } } int find(int x) { if (par[x]==x) { return x; } else { return par[x]=find(par[x]); } } void unite(int x, int y) { x=find(x); y=find(y); if (x==y) return; if (rank[x]<rank[y]) { par[x]=y; } else { par[y]=x; if (rank[x]==rank[y]) rank[x]++; } } bool same(int x, int y) { return find(x)==find(y); } }; struct edge { int u, v, cost; }; bool comp(const edge& a, const edge& b) { return a.cost<b.cost; } int n,m,r; edge es[50000]; int main() { int t; scanf("%d",&t); for (int ix=0; ix<t; ix++) { scanf("%d%d%d",&n,&m,&r); for (int i=0; i<r; i++) { int x, y, d; scanf("%d%d%d",&x,&y,&d); es[i]=(edge){x,y+n,-1*d}; } unionfind uf(n+m); sort(es, es+r, comp); ll res=10000*(n+m); for (int i=0; i<r; i++) { edge e=es[i]; // printf("%d %d\n",e.u,e.v); if (!uf.same(e.u,e.v)) { uf.unite(e.u,e.v); res+=e.cost; } } printf("%lld\n",res); } }
2030
ACM/ICPCの過去問だそうです。
DPです。解法みたら頭いいって思えました。はい。
#include <cstdio> #include <string> #include <iostream> using namespace std; int w,h; int dx[2]={-1,0}; int dy[2]={0,-1}; string mat[70]; string dp[70][70]; int main() { while (scanf("%d%d",&w,&h)){ if (!w&&!h) break; for (int i=0; i<70; i++) for (int j=0; j<70; j++) dp[i][j]=""; for (int i=0; i<h; i++) cin>>mat[i]; bool bef=false; if ('0'<mat[0][0]&&mat[0][0]<='9') { bef=true; dp[0][0]=mat[0][0]; } for (int i=1; i<w; i++) { if (bef&&'0'<=mat[0][i]&&mat[0][i]<='9') { dp[0][i]=dp[0][i-1]+mat[0][i]; } else if ('0'<mat[0][i]&&mat[0][i]<='9') { dp[0][i]=mat[0][i]; bef=true; } else if (mat[0][i]!='0') { bef=false; } } for (int i=1; i<h; i++) { for (int j=0; j<w; j++) { if ('0'<=mat[i][j]&&mat[i][j]<='9') { for (int k=0; k<2; k++) { int nx=i+dx[k], ny=j+dy[k]; if (nx>=0&&nx<h&&ny>=0&&ny<w) { int len=dp[i][j].length(), len2=dp[nx][ny].length()+1; if (len<len2&&len2!=1) dp[i][j]=dp[nx][ny]+mat[i][j]; else if (len==len2&&dp[i][j]<dp[nx][ny]+mat[i][j]) { dp[i][j]=dp[nx][ny]+mat[i][j]; } } } if (dp[i][j].length()==0&&mat[i][j]!='0') dp[i][j]=mat[i][j]; } } } int rlen=0; string rstr; for (int i=0; i<h; i++) { for (int j=0; j<w; j++) { if (rlen<dp[i][j].length()) { rlen=dp[i][j].length(); rstr=dp[i][j]; } else if (rlen==dp[i][j].length()&&rstr<dp[i][j]) { rstr=dp[i][j]; } } } cout<<rstr<<endl; } }
1458
LCS、向かってみたら自分がLCSの漸化式さえ考えつかないことにようやく気づきました・・・
蟻本
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; int main() { string x, y; while (cin>>x>>y) { int xlen=x.length(), ylen=y.length(); int dp[xlen+1][ylen+1]; for (int i=0; i<=xlen; i++) for (int j=0; j<=ylen; j++) dp[i][j]=0; for (int i=0; i<xlen; i++) { for (int j=0; j<ylen; j++) { if (x[i]==y[j]) { dp[i+1][j+1]=dp[i][j]+1; } else { dp[i+1][j+1]=max(dp[i+1][j],dp[i][j+1]); } } } printf("%d\n",dp[xlen][ylen]); } }
あれ?昨日やった一問以外本当に全部自力で解いたものがない・・・
2028
やるだけ問題付け加えた。自力だけど慰めにもならなかったw
#include <cstdio> int n, q; int cnt[101]; int main() { while (scanf("%d%d",&n,&q)) { if (!n&&!q) break; for (int i=0; i<101; i++) cnt[i]=0; for (int i=0; i<n; i++) { int m; scanf("%d",&m); for (int j=0; j<m; j++) { int day; scanf("%d",&day); cnt[day-1]++; } } int rcnt=0, res=0; for (int i=0; i<101; i++) { if (cnt[i]>=q&&rcnt<cnt[i]) { res=i+1; rcnt=cnt[i]; } } printf("%d\n",res); } }