首先 \(0<=a<=b<=c\)
会随机给出
\(a+b,a+c,b+c,a+b+c\)的值node
由于\(a,b,c\)都为正整数,因此\(a+b+c\)必定为最大值
而后用\(a+b+c\)逐个减去便可(注意\(a,b,c\)大小ios
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; int x[5]; int main(){ for(int i=1;i<=4;++i) cin>>x[i]; sort(x+1,x+5); for(int i=3;i>=1;--i) cout<<x[4]-x[i]<<" "; return 0; }
根据题意模拟,不难想到暴力枚举,枚举出每个由原数删了后的数
再看数据范围,数的长度最多十位,因此每一个数最多枚举2^10次,每次枚举最多10次,\(t<=10\)组数据
n为数的长度
因此时间复杂度\(O(2^n*n*t)\)spa
利用二进制
举个例子
原数\(2081\)
$(1010)_2 $ 1就表明不删相应位置数,0表明删了相应位置的数
按照上述规则,删了后的数为 28
\((0111)_2\) 删了后的数字为 081 ,但这里你会发现有前导0,但其实具体实现的时候不会有这个问题,由于咱们是一位一位的转化成整型,巧妙的避免了前导0的问题
既然是找最少次删除操做
那枚举顺序\(0-2^n\)code
#include<cstdio> #include<cmath> #include<cstring> #include<iostream> using namespace std; string s; int t; int stlen(int x){//求x的位数 int ans=0; for(;x;++ans) x/=10;return ans; } int main(){ cin>>t; while(t--){ cin>>s; int len=s.length(); int ans=100; for(int i=0;i<(1<<len);++i){ int x=0; for(int j=0;j<len;++j) if(i>>j & 1) x=x*10+s[j]-'0'; int sq=sqrt(x); if(x && sq*sq==x) ans=min(ans,len-stlen(x)); } if(ans!=100) cout<<ans<<endl; else cout<<"-1"<<endl; } }
突破口 :只且必须选出两个特殊点
那么考虑三种状况
设两个特殊点分别为\(x,y\)排序
选了\(x,y\)但不通过任意\(x,y\)ci
通过两个\(x,y\)最短路径是从\(1——>n\)get
通过两个\(x,y\)最短路径是从\(n——>1\)string
设\(dis1[],dis2[]\)分别为1到各个点的最短距离,n到各个点的最短距离
三种状况分别能得出的答案即为
1.\(dis1[n]\) (不通过任何点即为最短路
2.\(dis1[x]+1+dis2[y]\) (1——>x+x——>y+y——n
3.\(dis2[x]+1+dis1[y]\) (n——>x+x——>y+y——1it
求出后两种状况的最大值以后
在三者状况种取最小值(为何不取较大两个值,由于较大两个虽然构成最短路,但在三种状况一块儿讨论的时候,并不较大的两个值并不构成最短路
也就是说,添加一条边以后颇有可能最短距离会减少)io
第一状况跑一下最短路就可
第二种和第三种状况,首先要预处理
\(dis1[]和dis2[]\),跑一遍最短路便可
最终求的是1到n最短距离尽量大
因此如今的目标就是求出2,3状况的最大值,取其中得最小值(
若是暴力求话直接GG
假设\((i,j)\)为一对且\(i!=j\),并且i,j∈特殊点
任取一对,则二三状况获得的答案
\(max(min(dis1[i]+1+dis2[j],dis1[j]+dis[i]+1))\)
当dis1[i]+1+dis2[j]<=dis1[j]+dis[i]+1时
即dis1[i]-dis2[i]<=dis[j]-dis2[j];
将数对根据差值排序
此时
当数对后一个为x时
取max(dis1[1~x-1])+dis2[x])
x从1~k
取出的最大值,最后与dis1[n]取最小值便可
#include<cstdio> #include<cstring> #include<queue> #include<algorithm> #include<iostream> using namespace std; int n,m,k;const int maxn=2e5+10; int head[maxn*2]; int p[maxn]; int cnt=0; int dis1[maxn],dis2[maxn]; struct node{ int v,next; }e[maxn*2]; void add(int u,int v){ e[++cnt].v=v; e[cnt].next=head[u]; head[u]=cnt; } bool cmp(int a,int b){ return dis1[a]-dis2[a]<dis1[b]-dis2[b]; } void dj(int st,int dis[]){ bool vl[maxn]; memset(vl,0,sizeof(vl)); memset(dis,0x3f3f3f3f,maxn*4); dis[st]=0; priority_queue<pair<int,int> >q; q.push(make_pair(-dis[1],st)); while(!q.empty()){ int u=q.top().second;q.pop(); if(vl[u]) continue; vl[u]=1; for(int i=head[u];i;i=e[i].next){ int v=e[i].v; if(dis[v]>dis[u]+1){ dis[v]=dis[u]+1; q.push(make_pair(-dis[v],v)); } } } } int main(){ scanf("%d%d%d",&n,&m,&k);memset(head,0,sizeof(head)); for(int i=1;i<=k;++i) scanf("%d",&p[i]); for(int i=1;i<=m;++i){ int u,v;scanf("%d%d",&u,&v); add(u,v);add(v,u); } dj(1,dis1); dj(n,dis2); sort(p+1,p+1+k,cmp); int res=0,x=dis1[p[1]]; for(int i=2;i<=k;++i){ int t=p[i]; res=max(res,dis2[t]+x+1); x=max(x,dis1[t]); } printf("%d",min(res,dis1[n]));return 0; }