求切比雪夫距离之和最小。
要去的点在“中间”,于是我就算算中间的点就过了 。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn = 100005;
struct node{
int x,y;
}a[maxn];
LL dis(node a,node b){
LL dx=abs(a.x-b.x);
LL dy=abs(a.y-b.y);
return max(dx,dy);
}
int n;
LL ans,sum;
bool cmp1(node a,node b){
return a.x<b.x;
}
bool cmp2(node a,node b){
return a.y<b.y;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i].x,&a[i].y);
if(n<1000){
ans=1ll<<60,sum;
for(int i=1;i<=n;i++){
sum=0;
for(int j=1;j<=n;j++)sum+=dis(a[i],a[j]);
ans=min(ans,sum);
}
}else{
sort(a+1,a+1+n,cmp1);
ans=1ll<<60,sum;
int mid=(1+n)>>1;
for(int i=mid-100;i<=mid+100;i++){
sum=0;
for(int j=1;j<=n;j++)sum+=dis(a[i],a[j]);
ans=min(ans,sum);
}
sort(a+1,a+1+n,cmp2);
for(int i=mid-100;i<=mid+100;i++){
sum=0;
for(int j=1;j<=n;j++)sum+=dis(a[i],a[j]);
ans=min(ans,sum);
}
}
printf("%lld\n",ans);
}
供求平衡问题,费用流解决
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<queue>
using namespace std;
const int maxn = 2005;
const int mx[]={1,0,-1,0};
const int my[]={0,1,0,-1};
const char ch[]={'D','R','U','L'};
struct edge{
int x,y,next,v,c;
edge(){}
edge(int _x,int _y,int _nt,int _v,int _c)
:x(_x),y(_y),next(_nt),v(_v),c(_c){}
}e[maxn<<1];
int head[maxn],tot=1;
void addedge(int x,int y,int v,int c){
e[++tot]=edge(x,y,head[x],v,c);head[x]=tot;
e[++tot]=edge(y,x,head[y],0,-c);head[y]=tot;
}
int n,m,S,T=0;
int num[20][20],dis[maxn],fro[maxn];
bool inq[maxn];
queue<int>q;
bool SPFA(){
for(int i=S;i<=T;i++)dis[i]=0x3f3f3f3f;
dis[S]=0;q.push(S);inq[S]=1;
while(!q.empty()){
int x=q.front();q.pop();inq[x]=0;
for(int y,v,c,i=head[x];i;i=e[i].next){
y=e[i].y;v=e[i].v;c=e[i].c;
if(v && dis[y]>dis[x]+c){
dis[y]=dis[x]+c;
fro[y]=i;
if(!inq[y]){
inq[y]=1;q.push(y);
}
}
}
}
return dis[T]!=0x3f3f3f3f;
}
int mcf(){
int ret=0;
while(SPFA()){
int tmp=0x3f3f3f3f;
for(int i=fro[T];i;i=fro[e[i].x])tmp=min(tmp,e[i].v);
ret+=tmp*dis[T];
for(int i=fro[T];i;i=fro[e[i].x])e[i].v-=tmp,e[i^1].v+=tmp;
}
return ret;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
num[i][j]=++T;
char str[20];
for(int i=1;i<=n;i++){
scanf("%s",str+1);
for(int j=1;j<=m;j++){
for(int k=0;k<4;k++){
int x=i+mx[k];if(x>n)x=1;if(x<1)x=n;
int y=j+my[k];if(y>m)y=1;if(y<1)y=m;
int u=num[i][j];
int v=num[x][y]+n*m;
if(str[j]==ch[k])
addedge(u,v,1,0);
else
addedge(u,v,1,1);
}
}
}
S=0;T=n*m*2+1;
for(int i=1;i<=n*m;i++){
addedge(S,i,1,0);
addedge(i+n*m,T,1,0);
}
cout<<mcf()<<endl;
}
暴力KMP就能过
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<algorithm>
using namespace std;
char str[205][100005];
int id[205],len[205],ans[205];
int pre[100005];
int n;
bool cmp(int a,int b){
return len[a]<len[b];
}
int main(){
scanf("%d",&n);
#define str str[i]
#define len len[i]
for(int i=1;i<=n;i++){
scanf("%s",str+1);str[0]='$';
len=strlen(str+1);
}
#undef str
#undef len
#define str1 str[i]
#define str2 str[j]
#define len1 len[i]
#define len2 len[j]
#define ans ans[i]
for(int i=1;i<=n;i++){
memset(pre,0,sizeof(pre));
for(int fix=0,k=2;k<=len1;k++){
while(fix && str1[fix+1]!=str1[k])fix=pre[fix];
if(str1[fix+1]==str1[k])fix++;
pre[k]=fix;
}
ans=0;
for(int j=1;j<=n;j++){
if(len2<len1)continue;
for(int fix=0,k=1;k<=len2;k++){
while(fix && str1[fix+1]!=str2[k])fix=pre[fix];
if(str1[fix+1]==str2[k])fix++;
if(fix==len[i])ans++,fix=pre[fix];
}
}
}
for(int i=1;i<=n;i++)cout<<ans<<endl;
#undef ans
#undef str1
#undef str2
#undef len1
#undef len2
}