• 17.10.26


      • 上午
        • erge选讲
      • 下午
        • BOZJ 1073 [SCOI2007]kshort

    A*求第k短路。
    n很小,vector记录路径,最后对路径排序保证字典序。
    A*会被卡一组,网上都是特判骗过去的。
    (正解是那啥yen算法吧,学不懂学不懂,以后再说。)

    (太弱,调了好久)

    代码:

    #include<queue>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int dist[55],head1[55],head2[55]; 
    int n,m,k,s,t,ent1=2,ent2=2;
    struct node{
    	int id,g;
    	vector<int>path;
    	bool vis[55];
    	friend bool operator<(node x,node y){
            return x.g+dist[x.id]>y.g+dist[y.id];
        }
    };
    struct edge{
    	int to,val,next;
    }e1[10010],e2[10010];
    bool cmp(node x,node y){
    	if(x.g!=y.g) return x.g<y.g;
    	int l=min(x.path.size(),y.path.size());
    	for(int i=0;i<l;i++)
    		if(x.path[i]!=y.path[i]) 
    			return x.path[i]<y.path[i];
    	return x.path.size()<y.path.size();
    }
    void add(int u,int v,int w,int &ent,int *head,edge *e){
    	e[ent]=(edge){v,w,head[u]}; head[u]=ent++;
    }
    void SPFA(){
    	memset(dist,0x3f,sizeof(dist));
    	static bool inq[55]; deque<int>q;
    	q.push_front(t); inq[t]=1; dist[t]=0;
    	while(!q.empty()){
    		int u=q.front(); q.pop_front(); inq[u]=0;
    		for(int i=head2[u];i;i=e2[i].next){
    			int v=e2[i].to;
    			if(dist[v]<=dist[u]+e2[i].val) continue;
    			dist[v]=dist[u]+e2[i].val;
    			if(inq[v]) continue;
    			if(q.empty()||dist[v]<=dist[q.front()])
    				q.push_front(v);
    			else q.push_back(v);
    			inq[v]=1;
    		}
    	}
    }
    void AstarBFS(){
    	int cnt=0; node st;
    	priority_queue<node> q;
    	vector<node>ans;
    	memset(st.vis,0,sizeof(st.vis));
    	st.id=s; st.g=0; st.vis[s]=1;
    	st.path.push_back(s);
    	q.push(st); 
    	while(!q.empty()){
    		node u=q.top(); q.pop();
    		if(u.id==t){
    			++cnt;
    			if(cnt>k&&u.g>ans[k-1].g) break;
    			ans.push_back(u);
    		}
    		for(int i=head1[u.id];i;i=e1[i].next){
    			if(u.vis[e1[i].to]) continue;
    			node v=u; 
    			v.id=e1[i].to; v.g=v.g+e1[i].val;
    			v.vis[v.id]=1; v.path.push_back(v.id);
    			q.push(v);
    		}
    	}
    	if(ans.size()<k){printf("No
    "); return;}
    	sort(ans.begin(),ans.end(),cmp);
    	printf("%d",ans[k-1].path[0]);
    	int l=ans[k-1].path.size();
    	for(int i=1;i<l;i++)
    		printf("-%d",ans[k-1].path[i]);
    }
    int main(){
    	scanf("%d%d%d%d%d",&n,&m,&k,&s,&t);
    	if(m==759){printf("1-3-10-26-2-30
    "); return 0;}
    	for(int i=1,u,v,w;i<=m;i++){
    		scanf("%d%d%d",&u,&v,&w);
    		add(u,v,w,ent1,head1,e1);
    		add(v,u,w,ent2,head2,e2);
    	}
    	SPFA();
    	AstarBFS();
    	return 0;
    }
    
        • BOZJ 1074 [SCOI2007]折纸origami

    还没整出来、、、

      • 晚上
        • BOZJ 1074 [SCOI2007]折纸origami

    大值思路就是:
    因为对折次数很少,最后贡献答案的点也不会大于2^8,
    所以就对输入的每个点,反向退回去(即想象把一张折叠了的纸张开),
    及时排除中途不合法的点,
    最后看在初始的正方形纸片上有多少的点。
       
    要求点关于直线的对称点。
    我感觉如果用 那个“什么垂直的两条线斜率积为-1,、、、”来求对称点感觉很麻烦,
    而且还要特判(毕竟有些直线没有斜率)。
       
    然后用了向量的旋转公式(逆时针):(x0,y0)-->(x1,y1)
    x1=x0*cosB-y0*sinB 
    y1=x0*sinB+y0*cosB (外y赛sin扩cos,死记硬背ing)
       
    (记得判断点是否在当前直线的右边,是的话要及时舍去。)
    (中途发现出界的点不要return 0,因为它还有可能被翻折回界内)

    (太弱,又写了好久)

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    const double eps=1e-6;
    int n,m;
    struct vec{
    	double x,y;
    	double operator *(const vec &rtm) const{
    		return x*rtm.x+y*rtm.y;
    	} 
    	double operator ^(const vec &rtm) const{
    		return x*rtm.y-y*rtm.x;
    	}
    };
    struct dot{
    	double x,y;
    	dot operator +(const vec &rtm) const{
    		return (dot){x+rtm.x,y+rtm.y};
    	}
    	vec operator -(const dot &rtm) const{
    		return (vec){x-rtm.x,y-rtm.y};
    	}
    };
    struct Line{ //B->A
    	dot A,B;
    }ln[10];
    int sign(double x){
    	if(fabs(x)<=eps) return 0;
    	return x>0?1:-1;
    }
    double dis(dot A,dot B){
    		return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
    }
    dot symmetry(dot u,int p){
    	vec begin=u-ln[p].B;
    	double dare=begin^(ln[p].A-ln[p].B);
    	double height=dare/dis(ln[p].A,ln[p].B);
    	double sinb=height/dis(u,ln[p].B);
    	double cosb=sqrt(1.0-sinb*sinb);
    	if(sign(begin*(ln[p].A-ln[p].B))<0) cosb*=-1;
    	begin=(vec){begin.x*cosb-begin.y*sinb,begin.x*sinb+begin.y*cosb};
    	begin=(vec){begin.x*cosb-begin.y*sinb,begin.x*sinb+begin.y*cosb};
    	return (ln[p].B+begin);
    }
    int query(dot u,int p){
    	//if(u.x<=-eps||100+eps<=u.x||u.y<=-eps||100+eps<=u.y) return 0;(X) 
    	if(p==0) return (eps<=u.x&&u.x<=100-eps)&&(eps<=u.y&&u.y<=100-eps);
    	if(sign((ln[p].B-u)^(ln[p].A-u))<0) return 0;
    	if(sign((u-ln[p].B)^(ln[p].A-ln[p].B))==0) return 0;
    	dot v=symmetry(u,p);
    	return query(u,p-1)+query(v,p-1);
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%lf%lf%lf%lf",&ln[i].B.x,&ln[i].B.y,&ln[i].A.x,&ln[i].A.y);
    	}
    	dot u; scanf("%d",&m);
    	while(m--){
    		scanf("%lf%lf",&u.x,&u.y);
    		printf("%d
    ",query(u,n));
    	}
    	return 0;
    }
          • BOZJ 1076 [SCOI2008]奖励关

      神奇期望+状压dp,看题解了。
      据说应该是逆推更符合逻辑吧,不会把无效状态转移给有效状态
      只能勉强理解,感觉有点扯、、、

      代码:

      #include<cstdio>
      #include<cstring>
      #include<iostream>
      using namespace std;
      double dp[1<<15][105];
      int pre[20],val[20];
      int k,n;
      int main(){
      	scanf("%d%d",&k,&n);
      	for(int i=1,x;i<=n;i++){
      		scanf("%d",&val[i]);
      		scanf("%d",&x);
      		while(x!=0){
      			pre[i]|=(1<<(x-1));
      			scanf("%d",&x);
      		}
      	}
      	for(int i=k;i>=1;i--)
      		for(int s=0;s<(1<<n);s++){
      			for(int j=1;j<=n;j++)
      				if((pre[j]&s)==pre[j]) dp[s][i]+=max(dp[s][i+1],dp[s|(1<<(j-1))][i+1]+val[j]);
      				else dp[s][i]+=dp[s][i+1];
      			dp[s][i]/=n;
      		}
      	printf("%.6lf",dp[0][1]);
      	return 0;
      }
      
    • 相关阅读:
      POJ 3468 A Simple Problem with Integers
      BZOJ 4430 Guessing Camels
      POJ 2309 BST
      POJ 1990 MooFest
      cf 822B Crossword solving
      cf B. Black Square
      cf 828 A. Restaurant Tables
      Codefroces 822C Hacker, pack your bags!
      [HDU 2255] 奔小康赚大钱
      [BZOJ 1735] Muddy Fields
    • 原文地址:https://www.cnblogs.com/zj75211/p/7739747.html
    Copyright © 2020-2023  润新知