ICPC 2017 Japan Tsukuba(solve5/11)

题目链接:可以直接去Vj开题目 题目编号Aizu 1378-1388

A题

题意:给你一个容器,只能填方黑色和白色巧克力,黑色有1和k 2种规格,白色为1,问你在不超过l的情况下而且保证地段时黑色的情况下的方案数。

思想:DP  DP[i][j]  i=0为黑 1为白 i=0时候dp[i][j]=dp[1][j-1] i=1的时候 dp[i][j]=dp[i-1][j-1] + dp[i-1][j-k]//当j>=k的时候

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[2][105];//0黑1白 
int main()
{
	int l,k;
	while(scanf("%d%d",&l,&k)!=EOF)
	{
		memset(dp,0,sizeof(dp));
		dp[0][1]=1ll;
		dp[0][k]=1ll;
		for(int i=2;i<=l;i++)
		{
			dp[0][i]+=dp[1][i-1];
			dp[1][i]+=dp[0][i-1];
			if(i>=k)
				dp[1][i]+=dp[0][i-k];
		}
		ll ans=0;
		for(int i=1;i<=l;i++)
			ans+=dp[0][i];
		printf("%lld\n",ans);
	}
	return 0;
} 

B题

题意:给你n个点,问你最多可以有多少平行线,2个点只能连接一条线,一个点只能在一个线内。

思想:本来直接贪心斜率相等然后在算上垂直的,然后WA。想了想可能会出现很多斜率不等的,但是都可以凑成一对一对的,这样就只能爆搜了,直接dfs搜索。剪枝即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
struct node{
	int x;
	int y;
}no[20];
int ans,n;
int k1[20];
int k2[20];
int vis[20];
void dfs(int id,int sum)
{
	if(sum>=n/2)
	{
		int Ans=0;
		for(int i=0;i<sum;i++)
			for(int j=i+1;j<sum;j++)
				if(k1[i]*k2[j]==k2[i]*k1[j])
					Ans++;
		ans=max(ans,Ans);	
		return ;
	}
	if(vis[id])//当前被搞了 
		dfs(id+1,sum);
	else
	{
		for(int i=0;i<n;i++)
		{
			if(vis[i] || id==i)
				continue;
			k1[sum]=(no[i].y-no[id].y);
			k2[sum]=(no[i].x-no[id].x);
			vis[i]=1;
			vis[id]=1;
			dfs(id+1,sum+1);
			vis[i]=0;
			vis[id]=0;
		}
	} 
}
int main()
{
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	scanf("%d%d",&no[i].x,&no[i].y);
	dfs(0,0);
	printf("%d\n",ans);
}

 

C题

题意:给你n个人和一个t,每个人坚持每项的时间固定的a[i],问你t的时候n个人在检查或者等待检查某个项目。

思想:考虑下对于某个人来说他的最坏时间肯定是前边那个花费最多时间的那个人检查的项目,可以画画那个逻辑关系。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
ll  a[maxn];
int main()
{
	int n,m;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		for(int i=0;i<n;i++)
			scanf("%d",&a[i]);
		ll ans=0;
		ll temp = -1;
		for(int i=0;i<n;i++)
		{
			ans+=a[i];
			temp=max(temp,a[i]);
			if(m>=ans)
				printf("%lld\n",(m-ans)/temp+2);
			else
				printf("1\n");
		}
	}
	return 0;
}

F题

题意:给定一个有重边的带正权有向图,保证一开始有从 1 到 2 的路径。对于每条边,询问把它反向之后,从 1 到 2 的最短路如何变化。

思想:考虑翻转某条边对结果是否有影响,如果当前边是DAG图上的桥的话,肯定会让结果变差,如果不是桥的话,肯定是不变或者变小。重点是判断当前边是否是DAG图上的桥,就需要tarjan缩点判断是否是桥了。

当结点u的子结点v的后代通过反向边只能连回v,那么删除这条边(u, v)就可以使得图G非连通了。用Tarjan算法里面的时间戳表示这个条件,就是low[v]>dfn[u]。 

#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
const int INF = 0x3f3f3f3f;
typedef long long ll;
struct node{
	int to;
	int valu;
	int next;
	int flag;
}no[maxn],No[maxn*2];//正向 反向 
int head[maxn],Head[maxn];
int cnt,Cnt;
ll dist[maxn];//正向 
ll Dist[maxn];//反向 
void add(int u,int v,int valu,int flag)
{
	no[cnt].to=v;
	no[cnt].valu=valu;
	no[cnt].flag=flag;
	no[cnt].next=head[u];
	head[u]=cnt++;
} 
void Add(int u,int v,int valu,int flag)
{
	No[Cnt].to=v;
	No[Cnt].valu=valu;
	No[Cnt].flag=flag;
	No[Cnt].next=Head[u];
	Head[u]=Cnt++;
} 
void spfa(int u)
{
	memset(dist,INF,sizeof(dist));
	int vis[maxn]={0};
	queue<int>q;
	q.push(u);
	vis[u]=1;
	dist[u]=0;
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(int i=head[u];i!=-1;i=no[i].next)
		{
			int v=no[i].to;
			if(dist[v]>dist[u]+no[i].valu)
			{
				dist[v]=dist[u]+no[i].valu;
				if(vis[v]==0)
				{
					vis[v]=1;
					q.push(v); 
				}
			}
		}
	}
}
void Spfa(int u)
{
	memset(Dist,INF,sizeof(Dist));
	int vis[maxn]={0};
	queue<int>q;
	q.push(u);
	vis[u]=1;
	Dist[u]=0;
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(int i=Head[u];i!=-1;i=No[i].next)
		{
			int v=No[i].to;
			if(Dist[v]>Dist[u]+No[i].valu)
			{
				Dist[v]=Dist[u]+No[i].valu;
				if(vis[v]==0)
				{
					vis[v]=1;
					q.push(v); 
				}
			}
		}
	}
}
int dfn[maxn];
int low[maxn];
int is_bride[maxn];
int clo=1; 
void tarjan(int u,int pre)
{
	dfn[u]=low[u]=clo++;
	for(int i=Head[u];i!=-1;i=No[i].next)
	{
		int v=No[i].to;
		if(v!=pre)
		{
			if(dfn[v]==0)
			{
				tarjan(v,u);
				low[u]=min(low[u],low[v]);
				if(low[v] > dfn[u])
					is_bride[No[i].flag]=1;
			}
			else
				low[u]=min(low[u],low[v]);
		}
	}
}
int main()
{
	cnt=0;
	Cnt=0;
	memset(head,-1,sizeof(head));
	memset(Head,-1,sizeof(Head));
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		int u,v,valu;
		scanf("%d%d%d",&u,&v,&valu);
		add(u,v,valu,i);
		Add(v,u,valu,i);
	} 
	spfa(1);
	Spfa(2);	
	memset(Head,-1,sizeof(Head));
	Cnt=0;
	ll Max=dist[2];
	for(int i=1;i<=n;i++)
	{
		for(int j=head[i];j!=-1;j=no[j].next)
		{
			int v=no[j].to;
			if(dist[i]+Dist[v]+no[j].valu==Max)
			{
				
				Add(i,v,1,no[j].flag);
				Add(v,i,1,no[j].flag);
			}
		}
	}
	tarjan(1,-1);
	int ans[maxn]={0};
	for(int i=1;i<=n;i++)
	{
		for(int j=head[i];j!=-1;j=no[j].next)
		{
			if(dist[no[j].to]+Dist[i]+no[j].valu<Max)
				ans[no[j].flag]=1;
			else if(is_bride[no[j].flag])
				ans[no[j].flag]=-1;
		}
	}
	for(int i=1;i<=m;i++)
	{
		if(ans[i]==1)
			printf("HAPPY\n");
        else if(ans[i]==-1)
			printf("SAD\n");
        else
            printf("SOSO\n");
	}
	return 0;
 } 

I题

题意:有n个人乘车,有两种不同的预定票的方式,问你他们分别需要预留出来的最少的座位数量。但是保证所有人都坐下

①方法是允许客户随便 预定,就是想要那个就给你那个。②是最优的那种分配。

思想:对于第二种简单,需要最多的肯定是同时上车人数最多的时候。第一种的话,肯定是对于这n个人中某个人预定的区间的人数的最大值。

两个vis大小不一 。。

#include<bits/stdc++.h>
using namespace std;
int a[200005];
int b[200005];
int vis[100005];//标记上车 
int Vis[100005];//标记下车
int R[100005];//标记站点人 
int main()
{
    int n;
    scanf("%d",&n);
    int Max=-1;
    for(int i=0;i<n;i++)
    {
        scanf("%d%d",&a[i],&b[i]);
        vis[a[i]]++;//a[i]上车的人数 
        Vis[b[i]]++; //b[i]下车的人数
        R[a[i]]++;//记录总人数 
        R[b[i]]--; 
        Max=max(Max,b[i]);
    }
    long long ans1=0;
    long long ans2=0;
    long long temp=0;
    for(int i=1;i<=Max;i++)
    {
        temp+=R[i];
        ans2=max(temp,ans2);
        vis[i]+=vis[i-1];
        Vis[i]+=Vis[i-1];
    }
    for(int i=0;i<=n;i++)
        ans1=max(ans1,(long long)vis[b[i]-1]-Vis[a[i]]);//考虑的是区间最大值
         
    printf("%lld %lld\n",ans1,ans2);    
    return 0;
}

 

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可 6私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值