码迷,mamicode.com
首页 > 其他好文 > 详细

模拟测试(vj)

时间:2017-06-12 22:36:45      阅读:263      评论:0      收藏:0      [点我收藏+]

标签:map   其他   head   知识   价值   数学   ret   namespace   main   

做这份模拟测试,已经崩溃了,英文看不懂,题意理解错。到结束了只a了第一题,人生陷入了低谷,于是花了一天的时间终于把不会的弄明白了,在这里写一份总结~

T1,简单的模拟,如果打枪打中一支鸟,将这个位置设为0,并向两边扩散,注意这个位置一定要有鸟。

代码~

#include<bits/stdc++.h>
using namespace std;
int a[30000];
int n,m;

int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	cin>>m;
	for(int i=1;i<=m;i++)
	{
		int t1,t2;
		cin>>t1>>t2;
		if(a[t1]>=t2)
		{
			int l=t2-1,r=a[t1]-t2;
			a[t1-1]+=l,a[t1+1]+=r;
			a[t1]=0;
		}
	}
	for(int i=1;i<=n;i++)
		cout<<a[i]<<"\n";
    return 0;
}

 T2.dp的思想,我们设dp[i][t][w]表示在i个取完之后总厚度为t,上面的宽度为w,于是记忆化搜索就很好写出来啦(初始化dp为-1,为没有走过)

#include<bits/stdc++.h>
#define inf 120390420
using namespace std;
int w[300],t[300];
int n;
int f[300][300][300];
int dp(int i,int tt,int ww)
{
	if(tt>200||ww>200) return inf;
	if(i==n+1) return ww<=tt?tt:inf;
	int &ans=f[i][tt][ww];
	if(ans>=0) return ans;
	return ans=min(dp(i+1,tt+t[i],ww),dp(i+1,tt,ww+w[i]));
}

int main()
{
	cin>>n;
	memset(f,-1,sizeof(f));
	for(int i=1;i<=n;i++)
		cin>>t[i]>>w[i];
	cout<<dp(1,0,0)<<endl;
	return 0;
	
}

 附带同学的代码,背包的思想:将t看成费用,而w为价值,于是二分+背包就可以出来了,不过他好像没有用二分

#include<bits/stdc++.h>
using namespace std;
int n;
int t[200],w[200];
int f[200];
int sum=0,s=0;

int solve(int x)
{
	f[0]=0;
	for(int i=1;i<=x;i++) f[i]=-12214019;
	for(int i=1;i<=n;i++)
		for(int j=x;j>=t[i];j--)
			f[j]=max(f[j],f[j-t[i]]+w[i]);
	return x>=(s-f[x]);
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{	cin>>t[i]>>w[i];sum+=t[i];s+=w[i];}
	for(int i=1;i<=sum;i++)
		if(solve(i)) {
			cout<<i<<endl;break;
		}
	
    return 0;
}

 

T3.就是运用数学的知识,首先我们可以推出夹在两个1-1之间的0的个数是2^(n-1),而可重集合的全排列是等于C(num,a),C(num-a,b)以此类推,于是我们利用乘法原理就可以做出来了。组合数的话用杨辉三角,起点从0开始,这也算小技巧吧,get+,由于数据比较小,不用高精度快速幂,也感觉不错~

#include<bits/stdc++.h>
#define LL long long
#define mod 1000000007
using namespace std;
LL n,m;
LL b[2000000];
LL c[2000][2000];
vector<LL> q;
vector<LL> v;
int Pow(int a,int b)
{
	int ans=1;
	for(int i=1;i<=b;i++)
		ans=(ans*a)%mod;
	return ans%mod;
}

int main()
{
	cin>>n>>m;
	for(int i=0;i<=1000;i++) c[i][0]=1;
	for(int i=1;i<=1000;i++) 
		for(int j=1;j<=1000;j++)
			c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
	if(m==0) {cout<<"0\n";return 0;}
	for(LL i=1;i<=m;i++)
		cin>>b[i];
	b[0]=0;
	b[m+1]=n+1;
	sort(b,b+m+2);
	for(LL i=1;i<=m+1;i++)
		if(b[i]-b[i-1]>1){
			q.push_back(b[i]-b[i-1]-1);
			if(i!=1&&i!=m+1)
				v.push_back(b[i]-b[i-1]-1);	
		}
	LL tot=n-m, ans=1;
	for(LL i=0;i<q.size();i++)
	{
		ans*=c[tot][q[i]],ans%=mod;
		tot-=q[i];
	}	
	for(LL i=0;i<v.size();i++)
		ans*=Pow(2,v[i]-1),ans%=mod;
	cout<<ans<<endl;
	return 0;
}

 

 

T4.就是模拟,我们可以运用巧妙地办法,只计算在1,n或1,m中的次数,根据奇偶性,其中的碰撞次数应该为m+n-2,于是我们每一次计算的时候判断边界条件就可以了~

#include<bits/stdc++.h>
#define inf 12831240
#define LL long long
using namespace std;
LL n,m;

map<LL,LL> book[300000];
LL ans=1;
LL sx,sy;
LL x,y;
int main()
{
	cin>>n>>m;cin>>x>>y;
	char s[2];cin>>s;
	if(s[0]==‘D‘) sx=1;else sx=-1;
	if(s[1]==‘R‘) sy=1;else sy=-1;
	LL res=n+m-2;
	if(x==1||y==1||x==n||y==m) book[x][y]=1,res--;
	LL num=0;
	while(1)
	{
		LL dis=inf;
		num++;
		if(num>=1293821){ cout<<"-1";return 0;}
		if(sx==1) dis=min(dis,n-x);else dis=min(dis,x-1);
		if(sy==1) dis=min(dis,m-y);else dis=min(dis,y-1);
		x+=sx*dis,y+=dis*sy,ans+=dis;
		if(x==1) sx=1;else if(x==n) sx=-1;
		if(y==1) sy=1;else if(y==m) sy=-1;
		if(book[x][y]==0) book[x][y]=1,res--;
		if(res==0) {cout<<ans<<endl;return 0;}
	}
	
    return 0;
}

 T5.是一道树形dp,我们枚举所有的边,然后断掉这条边之后,在剩下的两个联通块中分别找出到各个节点距离之和最小的节点,然后和ans进行比较,比较的时候注意,很多小细节要加以深思,比如说/2,*的部分。我们可以设size[x]表示以x为根节点的子树的大小,f[x]表示x到各个位置的距离,然后根据关系就可以求解了,具体看代码的dfs和find部分~

#include<bits/stdc++.h>
#define maxn 124890
#define LL long long
using namespace std;
struct Edge{LL w,to,next;}e[maxn];
LL cnt=1,n;
LL ans=1e18;
LL head[maxn],f[maxn],sz[maxn];
void add(LL u,LL v,LL w)
{
	e[++cnt].to=v;
	e[cnt].w=w;
	e[cnt].next=head[u];
	head[u]=cnt;
}

void dfs(LL x,LL fa)
{
	f[x]=0,sz[x]=1;
	for(LL i=head[x];i;i=e[i].next)
	{
		LL j=e[i].to;
		if(j!=fa)
		{
			dfs(j,x);
			sz[x]+=sz[j],f[x]+=sz[j]*e[i].w+f[j];
		}
	}
}

LL find(LL x,LL fa,LL &p,LL num)
{
	p=min(p,f[x]);
//	cout<<x<<" "<<f[x]<<"\n"; 
	for(LL i=head[x];i;i=e[i].next)if(e[i].to!=fa)
	{
		f[e[i].to]=f[x]+(num-2*sz[e[i].to])*e[i].w;
		find(e[i].to,x,p,num);
	}
}

int main()
{
	cin>>n;
	for(LL i=1;i<=n-1;i++)
	{
		LL t1,t2,t3;
		cin>>t1>>t2>>t3;
		add(t1,t2,t3);
		add(t2,t1,t3);
	}
	LL i=2;
	while(i<=cnt)
	{
		dfs(e[i].to,e[i^1].to);
		dfs(e[i^1].to,e[i].to);
		LL p1=1e18,p2=1e18;
		find(e[i].to,e[i^1].to,p1,sz[e[i].to]);
		find(e[i^1].to,e[i].to,p2,sz[e[i^1].to]);
		LL sum=0;
		for(LL ii=1;ii<=n;ii++)
			sum+=f[ii];//表示该节点到其他节点的距离,算2倍 
		ans=min(ans,sum/2+sz[e[i].to]*sz[e[i^1].to]*e[i].w+p1*sz[e[i^1].to]+p2*sz[e[i].to]);
		i+=2;
	}
	cout<<ans<<endl;
	return 0;
}

 

模拟测试(vj)

标签:map   其他   head   知识   价值   数学   ret   namespace   main   

原文地址:http://www.cnblogs.com/foreverpiano/p/6995012.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!