17.10.04

  • 中秋节到了呢。
  • 上午
    • 入门OJ 2062: [Noip模拟题]计蒜姬

      看似搜索树很大,但仔细观察后发现:

      X=X-X这一操作好像没有用

      X=X/X也就最多提供一个值为1的状态

      那么就只剩下X=X+X和X=X*X这两个搜索方向,而且状态值的增长速度很快,那么一个BFS就好了

      代码:

      #include<queue> 
      #include<cstdio>
      #include<cstring>
      #include<iostream>
      #define ll long long
      #define node(a,b) (node){a,b}
      using namespace std;
      struct node{
      	ll val,stp;
      };
      queue<node> q;
      ll x,y;
      int main(){
      	scanf("%lld%lld",&x,&y);
      	q.push(node(x,0)); if(x!=1)q.push((node(1,1)));
      	node u; ll v;
      	while(!q.empty()){
      		u=q.front(); q.pop();
      		if(u.val==y) {printf("%lld",u.stp); exit(0);}
      		v=u.val*2; if(v<=y) q.push(node(v,u.stp+1));
      		v=u.val*u.val; if(v<=y&&v!=1) q.push((node(v,u.stp+1)));
      	}
      	printf("-1");
      	return 0;
      }
    • 入门OJ 2063: [Noip模拟题]修建道路

      又学到了一个套路。

      显然二分sub的花费,但一直没想到怎么判断是否存在一条从起点到终点的路径使得路径上花费大于sub的路段的数量小于等于k

      然后看了看题解,感觉很自己很智障……

      把大于二分值的路段的权值赋为1,小于等于的赋为0,跑个最短路,最后看终点的dis是否小于等k就好了。

      代码:

      #include<queue>
      #include<cstdio>
      #include<cstring>
      #include<iostream>
      using namespace std;
      struct edge{
      	int to,val,next;
      }e[10005];
      int head[1005],dis[1005];
      bool inq[1005];
      int n,m,k,ent=1,r=0,l=0,mid,ans=-1;
      void add(int u,int v,int w){
      	e[ent]=(edge){v,w,head[u]};
      	head[u]=ent++;
      }
      bool spfa(int lim){
      	memset(dis,0x3f,sizeof(dis));
      	memset(inq,0,sizeof(inq));
      	queue<int>q; q.push(1); dis[1]=0; inq[1]=1;
      	while(!q.empty()){
      		int u=q.front(); q.pop(); inq[u]=0;
      		for(int i=head[u];i;i=e[i].next){
      			int v=e[i].to;
      			int w=e[i].val>lim?1:0;
      			if(dis[v]<=dis[u]+w) continue;
      			dis[v]=dis[u]+w;
      			if(inq[v]) continue;
      			q.push(v);
      			inq[v]=1;
      		}
      	}
      	return dis[n]<=k;
      } 
      int main(){
      	scanf("%d%d%d",&n,&m,&k);
      	for(int i=1,a,b,c;i<=m;i++){
      		scanf("%d%d%d",&a,&b,&c);
      		add(a,b,c); add(b,a,c);
      		r=max(r,c);
      	}
      	while(l<=r){
      		mid=(l+r)/2;
      		if(spfa(mid)) ans=mid,r=mid-1;
      		else l=mid+1;
      	}
      	printf("%d",ans);
      	return 0;
      }
      
    • 然后一直在看后两个题,一直不会……
  • 下午
    • 入门OJ 2068: [Noip模拟题]最长上升子序列

      又是一道神奇的题……

      应该是构造类吧,不看题解我真的做不出来

      image

      直接贴上题解,这只是一种构造方法。

      也就是说答案不唯一,OJ好像不支持spj,交了就wa。

      手测了一些数据,都过了,就当是AC了吧……真是伤脑筋。

      代码:

      #include<cstdio>
      #include<iostream>
      #include<cstring>
      #include<vector>
      #define N 100005
      using namespace std;
      int f[N],a[N];
      bool vis[N];
      vector<int>v[N];
      int main()
      {
      	int T;
      	cin>>T;
      	vis[0]=1;
      	while(T--)
      	{
      		int n;
      		cin>>n;
      		memset(vis+1,0,n);
      		for(int i=1;i<=n;i++) v[i].clear();
      		bool ok=1;
      		for(int i=1;i<=n;i++)
      		{
      			scanf("%d",&f[i]);
      			v[f[i]].push_back(i);
      			if(!vis[f[i]-1]) ok=0;
      			vis[f[i]]=1;
      		}
      		if(!ok) {puts("No");continue;}
      		for(int i=1,tail=1;!v[i].empty();i++)
      			for(int j=v[i].size()-1;j>=0;j--)
      				a[v[i][j]]=tail++;
      		for(int i=1;i<=n;i++) printf("%d ",a[i]);
      		cout<<endl;
      	}
      	return 0;
      }
    • 入门OJ 2069: [Noip模拟题]贪吃的CW

      很不错的一道

      直接看题解吧,真的想不出来。

      但WA了,只有明天改了0.0

  • 晚上

          • 因为中秋节,今晚向老师申请到可以皮皮,大家去用投影仪看电影去了然后沐然过生,吃蛋糕呢。
    • End

……很胀……

 

posted @ 2017-10-04 08:41  *ZJ  阅读(162)  评论(0编辑  收藏  举报