• 17.11.08


      • 上午 模拟考试
          • Prob.1(WA30

        模拟,有点小烦。然后double转整型时没有long long,挂了3个点。

        • Prob.2(WA70

    简化题目
    给出了一个图(n点数<=2500)的两点间的最短距离的邻接矩阵。
    问是否存在一颗 n个点的树的邻接矩阵和输入的相同。 (没有负权)

    可以发现,如果存在的话,当前邻接表中最小的边一定是树中的一条边。
    所以就 最小生成树prim算法,不用优先队列 n^2

    然后就是求出当前树的两点间距离的邻接矩阵。比对就好了。
    跑n次dfs就出来了 n^2

    (智障的我:怎么求树上所有点之间的距离啊,Floyd n^3 要炸啊。简直莫法做,看来只能得30分了)
    (、、、、Floyd?!蛤,我在干嘛、、)
    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    #define MAXN 2505
    #define INF 0x3f3f3f3f
    using namespace std;
    struct edge{
    	ll to,val,next;
    }e[MAXN*2];
    ll ans[MAXN][2];
    ll head[MAXN],fa[MAXN],mp[MAXN][MAXN],dis[MAXN][MAXN];
    ll n,ent;
    char gc(){
    	static char s[100005];
    	static int bit=100000,p,len;
    	if(p>=len) len=fread(s,1,bit,stdin),s[len]=EOF,p=0;
    	return s[p++];
    }
    void read(ll &x){
    	static int f;static char ch;
    	x=0; f=1; ch=gc();
    	while(ch<'0'||'9'<ch){if(ch=='-')f=-1;ch=gc();}
    	while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=gc();}
    	x=x*f;
    }
    void add(ll u,ll v,ll w){
    	e[ent]=(edge){v,w,head[u]};
    	head[u]=ent++;
    }
    void Prim(){
    	static ll d[MAXN],from[MAXN];
    	static bool vis[MAXN];
    	memset(vis,0,sizeof(vis));
    	memset(d,0x3f,sizeof(d));
    	memset(head,0,sizeof(head));
    	vis[1]=1; ent=2;
    	for(ll i=2;i<=n;i++) if(d[i]>mp[1][i]) d[i]=mp[1][i],from[i]=1;
    	for(ll k=1,w,v;k<n;k++){
    		w=INF;
    		for(ll i=1;i<=n;i++) if(!vis[i]&&w>d[i]) w=d[i],v=i;
    		add(from[v],v,w); add(v,from[v],w); vis[v]=1;
    		ans[from[v]][0]+=w; ans[v][0]+=w; 
    		ans[from[v]][1]+=1; ans[v][1]+=1; 
    		for(ll i=1;i<=n;i++) if(!vis[i]&&d[i]>mp[v][i]) d[i]=mp[v][i],from[i]=v;
    	}
    }
    void dfs(ll u,ll dad,ll val,ll *DIS){
    	DIS[u]=val;
    	for(ll i=head[u];i;i=e[i].next){
    		ll v=e[i].to;
    		if(v==dad) continue;
    		dfs(v,u,val+e[i].val,DIS);
    	}
    }
    void check(){
    	bool fg=1;
    	for(ll i=1;i<=n;i++)
    		for(ll j=1;j<=n;j++)
    			if(dis[i][j]!=mp[i][j]){fg=0;break;}
    	if(!fg) printf("No
    ");
    	else{
    		double val=1.0*ans[1][0]/ans[1][1];ll ANS=1;
    		for(ll i=2;i<=n;i++) if(1.0*ans[i][0]/ans[i][1]>val) 
    			val=1.0*ans[i][0]/ans[i][1],ANS=i;
    		printf("Yes
    %I64d
    ",ANS);
    	}
    }
    void work(){
    	read(n);
    	for(ll i=1;i<=n;i++)
    		for(ll j=1;j<=n;j++)
    			read(mp[i][j]);
    	Prim();
    	for(ll i=1;i<=n;i++) dfs(i,0,0,dis[i]);
    	check();
    }
    void init(){
    	memset(ans,0,sizeof(ans));
    	memset(dis,0,sizeof(dis));
    	ent=0;
    }
    int main(){
    	freopen("treas.in","r",stdin);
    	freopen("treas.out","w",stdout);
    	ll T;
    	read(T);
    	while(T--){
    		init();
    		work();
    	}
    	return 0;
    }
        • Prob.3(WA10
        • 一个处理区间覆盖的题。他们都大佬地用O(n)做,我却在弱弱地用线段树维护、、、(就当复习了。)
        • 注意!!!

          1).这种题用到线段树的话,是以单位区间为底层节点的,方便。

          2).离散化后,要在没有紧贴的点中间加入一些 "占位点")
          (要不是数据善良,不然今天就又凉了)

      • 补两个Tyvj上的题,之前忘了记录了。
      • Tyvj P1480 星际大战

    状压dp,
    dp[S]表示选了"目标"集合为S的元素,这些元素依次被前几个导弹攻击的最小距离和。
    然后刷表法,即枚举下一个导弹打哪个目标。
    复杂度:2^n*n

    代码:

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    const double eps=1e-6;
    struct pos{
    	int x,y;
    }mis[25],aim[25];
    double d[25][25],dp[1<<20],hv[1<<20];
    int n,all;
    int idx(int i){
    	return 1<<i;
    }
    int sign(double x){
    	if(fabs(x)<=eps) return 0;
    	return x>0?1:-1;
    }
    void cmin(double &a,double b){
    	if(sign(a-b)>0) a=b;
    }
    double dis(pos a,pos b){
    	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    int main(){
    	scanf("%d",&n); all=(1<<n)-1;
    	for(int i=0;i<n;i++) scanf("%d%d",&mis[i].x,&mis[i].y);
    	for(int i=0;i<n;i++) scanf("%d%d",&aim[i].x,&aim[i].y);
    	for(int i=0;i<n;i++) for(int j=0;j<n;j++) d[i][j]=dis(mis[i],aim[j]);
    	for(int S=1;S<=all;S++) hv[S]=hv[S>>1]+(S&1),dp[S]=1e9;
    	for(int S=0,p;S<all;S++)
    		for(int i=0;i<n;i++){
    			if(S&idx(i)) continue;
    			p=hv[S]; cmin(dp[S|idx(i)],dp[S]+d[p][i]);
    		}
    	printf("%.3lf",dp[all]);
    	return 0;
    }
    
      • Tyvj P4112 删数问题

    贪心,依次确定最高位。
    显然在可取范围内,最高位越小越好,那么每次就查询可行区间的最小值的位置。
    线段树维护(尝试了一下ZKW线段树,感觉很像镜像对称后的树状数组。)
    (但是不会区间修改,感觉好麻烦啊,需要区间修改是我还是先直接打线段树吧)

    代码:

    #include<cstring>
    #include<iostream>
    #define MAXN 800
    using namespace std;
    char s[300],ans[300];
    struct ZKW{
    	int mini[MAXN],pos[MAXN],M,N;
    	void update(int &fmini,int &fpos,int smini,int spos){
    		if(fmini<smini) return;
    		if(fmini==smini&&fpos<spos) return;
    		fmini=smini; fpos=spos;
    	}
    	void build(int n){
    		memset(mini,0x3f,sizeof(mini));
    		for(M=1;M<=n+1;M<<=1); N=n;
    		for(int i=1;i<=n;i++) mini[M+i]=s[i]-'0',pos[M+i]=i;
    		for(int i=M;i;i--) 
    			update(mini[i],pos[i],mini[i<<1],pos[i<<1]),
    			update(mini[i],pos[i],mini[i<<1|1],pos[i<<1|1]);
    	}
    	int query(int l,int r){
    		int v=0x3f3f3f3f,p;
    		l=M+l-1;	r=M+r+1;
    		for(;l^r^1;l>>=1,r>>=1){
    			if(~l&1) update(v,p,mini[l^1],pos[l^1]);
    			if(r&1) update(v,p,mini[r^1],pos[r^1]);
    		}
    		return p;
    	}
    }T;
    int main(){
    	int n,m,k,cnt=0,now=0;
    	scanf("%s",s+1); n=strlen(s+1);
    	T.build(n); int last=0;
    	scanf("%d",&m); k=n-m;
    	while(k){
    		int p=T.query(last+1,last+m+1);
    		ans[++cnt]=s[p];
    		m-=(p-last-1); k--;
    		last=p;
    	};
    	for(int i=1;i<=cnt;i++) now=now*10+ans[i]-'0';
    	printf("%d",now);
    	return 0;
    }
  • 相关阅读:
    【转】Windows2012设置文件夹权限报错:failed to enumerate objects in the container.
    Vue 中背景图片路径怎么加参数?
    C#有小数位数直接进位为整数;JavaScript Math有小数位数取整方法
    C# Linq to Entity使用Groupby查询时超时或很慢解决思路
    colModel的设置(给单元格指定颜色等)
    金额的表示方法
    jqGrid表格时间格式化 ,formatoptions: {srcformat:'Y-m-d H:i:s',newformat:'Y-m-d H:i:s H:i:s'}
    HTTP Error 414. The request URL is too long. asp.net解决方案
    radio/checkbox各种操作
    Kubernetes常用命令总结
  • 原文地址:https://www.cnblogs.com/zj75211/p/7811432.html
Copyright © 2020-2023  润新知