7.7 NOIP 2014

NOIP 2014 DAY1

T1
在这里插入图片描述
纯模拟题,没有难度(也只有这道能a哈哈哈)

#include<bits/stdc++.h>
using namespace std;
int n,a1,b1,a[10000],b[10000],k1=1,k2=1,sum1,sum2;
int main(){
	//freopen("rps.in","r",stdin);
	//freopen("rps.out","w",stdout);
	cin>>n>>a1>>b1;
	for(int i=1;i<=a1;i++){
		cin>>a[i];
	}
	for(int i=1;i<=b1;i++){
		cin>>b[i];
	}
	for(int i=1;i<=n;i++){
		if(k1==a1+1){
			k1=1;
		}
		if(k2==b1+1){
			k2=1;
		}
		if(b[k2]==a[k1]){
				k1++;
				k2++;
				continue;
			}
		if(a[k1]==0){
			if(b[k2]!=2&&b[k2]!=3){
				sum2++;
			}
			else sum1++;
		}
		else if(a[k1]==1){
			if(b[k2]!=0&&b[k2]!=3){
				sum2++;
			}
			else sum1++;
		}
		else if(a[k1]==2){
			if(b[k2]!=1&&b[k2]!=4){
				sum2++;
			}
			else sum1++;
		}
		else if(a[k1]==3){
			if(b[k2]!=2&&b[k2]!=4){
				sum2++;
			}
			else sum1++;
		}
		else if(a[k1]==4){
			if(b[k2]!=0&&b[k2]!=1){
				sum2++;
			}
			else sum1++;
		}
		k1++;k2++; 
	}
	cout<<sum1<<" "<<sum2;
} 

T2
在这里插入图片描述
这道题我拿到是就想到了暴力,先是用vector给每个点加边,然后直接对每个点判断

#include<bits/stdc++.h>
#define mo 10007
using namespace std;
vector<int>v[200000];
long long n,a,b,maxx,sum,val,ans;
long long num[200000],x[200000];
void dfs(int n){
	sum=0; 
	for(int i=0;i<v[n].size();i++){
		for(int j=0;j<v[n].size();j++){
			if(i!=j){val=x[v[n][i]]*x[v[n][j]];
			maxx=max(val,maxx);
				sum+=maxx;       //这里写错了就wa了 改成val就有70分
			} 
		}

	}
	ans+=sum%mo;
	return ;
}
int main(){
//	freopen("link.in","r",stdin);
	//freopen("link.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n-1;i++){
		cin>>a>>b;
		v[a].push_back(b);
		v[b].push_back(a);
		num[a]++;
		num[b]++;
	}
	for(int i=1;i<=n;i++){
		cin>>x[i];
	}
	for(int i=1;i<=n;i++){
		if(num[i]>=2) dfs(i);
	}
	cout<<maxx<<" "<<ans%mo;
}

但是这样依然不能过,我们可以进一步优化,因为每个点都会计算与之相连的点的乘积,这是就用上了乘法的神奇预算,然后最大值求的时候我们可以先排个序,然后只判断前两个的值即可

#include<bits/stdc++.h>
#define mo 10007
using namespace std;
vector<int>v[200000];
long long n,x,y,maxx,sum,val,ans;
long long num[200000],a[200000];
bool cmp(int x,int y){
    return a[x]>a[y];
}
int main(){
//	freopen("link.in","r",stdin);
	//freopen("link.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n-1;i++){
		cin>>x>>y;
		v[x].push_back(y);
		v[y].push_back(x);
	}
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	 for(int i=1;i<=n;++i){
        if(v[i].size()<2) continue;
        sort(v[i].begin(),v[i].end(),cmp);
        maxx=max(maxx,a[v[i][0]]*a[v[i][1]]);
        int s=0;
        for(int j=0;j<v[i].size();++j)
            s+=a[v[i][j]];
        for(int j=0;j<v[i].size();++j)
            sum=((1ll*(s-a[v[i][j]]+10007)*a[v[i][j]])%10007+sum)%10007;
    }

	cout<<maxx<<" "<<sum;
}

T3
在这里插入图片描述

DAY 2

T1
在这里插入图片描述
也是一个模拟题,直接暴力,注意边界

#include<bits/stdc++.h>
using namespace std;
int d,n,m,x,y,z,sum,ans1,ans2,lx,ly,rx,ry;
int a[10001][10001];
int main(){
	//freopen("wireless.in","r",stdin);
//	freopen("wireless.out","w",stdout);
	cin>>d;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>x>>y>>z;
		a[x][y]=z;
	} 
	for(int i=0;i<=128;i++){
	lx=max(0,i-d),rx=min(d+i,128);
		for(int j=0;j<=128;j++){
			ly=max(0,j-d),ry=min(d+j,128);
			sum=0;
			for(int x=lx;x<=rx;x++){
				for(int y=ly;y<=ry;y++){
					sum+=a[x][y];
				}	
			}
			if(sum>ans2) ans2=sum,ans1=1;
			else if(sum==ans2) ans1++;
		}
	}
	cout<<ans1<<" "<<ans2;
}

T2
在这里插入图片描述
这道题经过dalao讲了一下还是有点思路,多试了几次还是做出来了(自学spfa)。其实主要就是删除不与终点连通的点,以及与他们连一条边的点。删除这个操作我们常用打标记的方法,在枚举图的时候遇到没打标记的点就跳过即可。最后直接跑最短路。

#include<bits/stdc++.h> 
using namespace std;
struct ed{
    int u;
    int nex;
}e[300000];
int n,m,x,y,d[300000],fir[20000],st,s,t;
bool v[20000],ok[20000],vis[20000];
void add(int u,int v)
{
    e[++st].u=u; e[st].nex=fir[v]; fir[v]=st;
}
void spfa(int b)  //最短路 
{
    memset(v,0,sizeof(v));
    memset(d,0x3f3f,sizeof(d));
    queue<int> q; q.push(b); v[b]=1; d[b]=0;
    while (!q.empty())
    {
        int k=q.front(); q.pop(); v[b]=0;
        for (int i=fir[k];i;i=e[i].nex)
        {
            int u=e[i].u,w=1;
            if (d[u]>d[k]+w&&ok[e[i].u]) {
                d[u]=d[k]+w;
                if (!v[u]) v[u]=1,q.push(u);
            }   
        }
    }
}

void bfs(int t)  //第一次的搜边 
{
    memset(v,0,sizeof(v));
    queue<int> q; q.push(t); ok[t]=v[t]=1;
    while (!q.empty())
    {
        int k=q.front(); q.pop();
        for (int i=fir[k];i;i=e[i].nex)
        if (!v[e[i].u]){
            int u=e[i].u; if (!v[u]) v[u]=1,ok[u]=1,q.push(u);
        }
    }
}
int main()
{
    cin>>n>>m;
    for (int i=1;i<=m;i++) cin>>x>>y,add(x,y);
    cin>>s>>t; 
    bfs(t);
    for (int i=1;i<=n;i++) vis[i]=ok[i];
    for (int i=1;i<=n;i++) 
    if (!vis[i]) for (int j=fir[i];j;j=e[j].nex){
    if (ok[e[j].u]) ok[e[j].u]=0; 
    }
    spfa(t);
    if (d[s]>=(0x3f3f)) cout<<"-1"<<endl;
    else cout<<d[s]<<endl;
    retrun 0;
}

T3
在这里插入图片描述

在这里插入代码片

两道T3还没啃透暂时先不贴代码后面再补上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值