【TJOI2013 Day1合集】BZOJ3170 松鼠聚会 BZOJ3171 循环格 BZOJ3172 单词
松鼠聚会:
首先题目给出的松鼠之间的距离应该是max(|x1-x2|,|y1-y2|)、、
然后我们知道、如果用x'=x+y,y'=x-y的方式重构所有点的坐标、
两个点之间的距离就变成了max(|x1'-x2'|,|y1'-y2'|)、、
于是我们用给的两个数字解一个一元二次方程得到原来的坐标、、
然后前缀和乱搞搞统计曼哈顿距离和就好了、
Code:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <vector>
#include <set>
#include <map>
#include <queue>
#define ps system("pause")
#define message printf("*\n")
#define pb push_back
#define X first
#define Y second
#define PII pair<int,int>
#define rep(a,b,c) for(int a=b;a<=c;a++)
#define per(a,b,c) for(int a=b;a>=c;a--)
typedef long long ll;
using namespace std;
struct node{
double x,y;
int id;
}p[100010];
bool cmp1(node a,node b){
return a.x<b.x;
}
bool cmp2(node a,node b){
return a.y<b.y;
}
double sx=0,sy=0,ts;
double ans[100010];
int n;
int main(){
scanf("%d",&n);
rep(i,1,n){
double xx,yy;
scanf("%lf%lf",&xx,&yy);
p[i].x=(xx+yy)/2;p[i].y=(xx-yy)/2;
sx+=p[i].x;sy+=p[i].y;p[i].id=i;
}
sort(p+1,p+n+1,cmp1);ts=0;
rep(i,1,n){
ans[p[i].id]+=(i-1)*p[i].x-ts;
ans[p[i].id]+=(sx-ts)-(n-i+1)*p[i].x;
ts+=p[i].x;
}
sort(p+1,p+n+1,cmp2);ts=0;
rep(i,1,n){
ans[p[i].id]+=(i-1)*p[i].y-ts;
ans[p[i].id]+=(sy-ts)-(n-i+1)*p[i].y;
ts+=p[i].y;
}
double s=1e18;
rep(i,1,n) s=min(s,ans[i]);
printf("%.0lf\n",s);
return 0;
}
循环格:
或许可以生成所有合法状态之后按行或者列方向做状压DP、、
但是我太弱了于是写了费用流、
图形成完美循环的充要条件是每个点的入度和出度都是1、、
于是拆点为入和出、由S向入i,T向出i分别连容量为1费用为0的边、、
对每个点入i,向相邻点的出j连容量为1的边、、
然后在最后的最大流中入i到出j如果存在流量就代表i上字母是指向j的、、
所以对原有的字母指向的边费用为0,因为不用修改、其它的就是1了、、
最后跑mincost-maxflow就好了、、
Code:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <vector>
#include <set>
#include <map>
#include <queue>
#define ps system("pause")
#define message printf("*\n")
#define pb push_back
#define X first
#define Y second
#define PII pair<int,int>
#define rep(a,b,c) for(int a=b;a<=c;a++)
#define per(a,b,c) for(int a=b;a>=c;a--)
typedef long long ll;
using namespace std;
#define inf 9999999
int l,r=2,n,m,S,T;
char c[20][20];
int t[100010],w[100010],v[100010],next[100010],s[100010];
int g[2010],e[2010],d[2010],fr[2010],uc[2010],ans=0;
bool ud[2010];
bool vis[1010];
int in[20][20],ou[20][20];
void addedge(int aa,int bb,int cc,int vv){
//printf("%d %d %d %d\n",aa,bb,cc,vv);
t[r]=bb;w[r]=cc;v[r]=vv;
if (!ud[aa]) g[aa]=e[aa]=r,ud[aa]=true;
else next[e[aa]]=r,e[aa]=r;
r++;
t[r]=aa;w[r]=0;v[r]=-vv;
if (!ud[bb]) g[bb]=e[bb]=r,ud[bb]=true;
else next[e[bb]]=r,e[bb]=r;
r++;
}
bool spfa(){
l=1;r=1;s[1]=S;
memset(vis,0,sizeof vis);
memset(fr,0,sizeof fr);
memset(uc,0,sizeof uc);
rep(i,S,T) d[i]=inf;
d[S]=0;vis[S]=true;
while (l<=r){
for (int u=g[s[l]];u;u=next[u])
if (w[u] && d[t[u]]>d[s[l]]+v[u]){
d[t[u]]=d[s[l]]+v[u];
fr[t[u]]=s[l];uc[t[u]]=u;
if (!vis[t[u]]){
s[++r]=t[u];
vis[t[u]]=true;
}
}
vis[s[l]]=false;
l++;
}
return d[T]!=inf;
}
int argu(){
int cur=T,res=inf,flow=0;
while (cur!=S){
res=min(res,w[uc[cur]]);
flow+=v[uc[cur]];
cur=fr[cur];
}
cur=T;
while (cur!=S){
w[uc[cur]]-=res;
w[uc[cur]^1]+=res;
cur=fr[cur];
}
return res*flow;
}
int main(){
scanf("%d%d\n",&n,&m);
rep(i,1,n){
scanf(" ");
rep(j,1,m) c[i][j]=getchar();
}
rep(i,1,n) rep(j,1,m){
in[i][j]=(i-1)*m+j;
ou[i][j]=in[i][j]+n*m;
}
S=0,T=n*m*2+1;
rep(i,1,n) rep(j,1,m){
addedge(S,in[i][j],1,0);
addedge(ou[i][j],T,1,0);
switch (c[i][j]){
case 'L':
addedge(in[i][j],ou[i][(j-1-m)%m+m],1,0);
addedge(in[i][j],ou[i][j%m+1],1,1);
addedge(in[i][j],ou[(i-1-n)%n+n][j],1,1);
addedge(in[i][j],ou[i%n+1][j],1,1);
break;
case 'R':
addedge(in[i][j],ou[i][(j-1-m)%m+m],1,1);
addedge(in[i][j],ou[i][j%m+1],1,0);
addedge(in[i][j],ou[(i-1-n)%n+n][j],1,1);
addedge(in[i][j],ou[i%n+1][j],1,1);
break;
case 'U':
addedge(in[i][j],ou[i][(j-1-m)%m+m],1,1);
addedge(in[i][j],ou[i][j%m+1],1,1);
addedge(in[i][j],ou[(i-1-n)%n+n][j],1,0);
addedge(in[i][j],ou[i%n+1][j],1,1);
break;
case 'D':
addedge(in[i][j],ou[i][(j-1-m)%m+m],1,1);
addedge(in[i][j],ou[i][j%m+1],1,1);
addedge(in[i][j],ou[(i-1-n)%n+n][j],1,1);
addedge(in[i][j],ou[i%n+1][j],1,0);
break;
}
}
while (spfa()) ans+=argu();
printf("%d\n",ans);
return 0;
}
单词:
这题有一万种方法可以做、、弱*的LZ就用KMP水过了、、
大致还可以用SA、AC自动机、字符串HASH之类的过吧、、
Code:
var
n,i,j,cur,k,p,ans:longint;
s:array [0..2000010] of char;
ff:array [0..2000010] of longint;
st,len:array [0..201] of longint;
w:array [0..201,0..100010] of char;
begin
readln(n);
cur:=0;
for i:=1 to n do
begin
st[i]:=cur+1;p:=0;
while not eoln do
begin
inc(cur);
read(s[cur]);
inc(p);
w[i][p]:=s[cur];
end;
len[i]:=p;
inc(cur);s[cur]:='#';
readln;
end;
for i:=1 to n do
begin
ff[1]:=0;k:=0;
for j:=2 to len[i] do
begin
while (k>0) and (w[i][k+1]<>w[i][j]) do k:=ff[k];
if w[i][k+1]=w[i][j] then inc(k);
ff[j]:=k;
end;
k:=0;ans:=0;
for j:=1 to cur do
begin
while (k>0) and (w[i][k+1]<>s[j]) do k:=ff[k];
if w[i][k+1]=s[j] then inc(k);
if k=len[i] then
begin
inc(ans);
k:=ff[k];
end;
end;
writeln(ans);
end;
end.

浙公网安备 33010602011771号