zoukankan      html  css  js  c++  java
  • 【USACO1.4】解题报告

    前言

    本章主要考的是贪心和一些比较麻烦的模拟。难度相比上一章有很明显的提升。但是稍微想一下还是可以想出来的(第五题除外,看了一下题解的思路)。
    USACO:http://train.usaco.org


    1.4.2.Mixing Milk

    思路:

    很明显是一道贪心基础题。肯定是要先买每单位价钱最便宜的,然后再依次买贵的。这个不用证明了吧。。。

    代码:

    /*
    ID:ssl_zyc2
    TASK:milk
    LANG:C++
    */
    
    #include <cstdio>
    #include <algorithm>
    #define N 5100
    using namespace std;
    
    int n,m,ans;
    
    struct node
    {
    	int p,d;
    }a[N];
    
    bool cmp(node x,node y)
    {
    	return x.p<y.p;
    }
    
    int main()
    {
    	freopen("milk.in","r",stdin);
    	freopen("milk.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=m;i++)
    	 scanf("%d%d",&a[i].p,&a[i].d);
    	sort(a+1,a+1+m,cmp);  //以价格排序
    	for (int i=1;i<=m;i++)
    	 if (a[i].d<n)  //可以全部买完
    	 {
    	 	n-=a[i].d;  //全部买完
    	 	ans=ans+a[i].d*a[i].p;
    	 }
    	 else 
    	 {
    	 	ans=ans+a[i].p*n;  //将不够的部分买完
    	 	break;
    	 }
    	printf("%d\n",ans);
    	return 0;
    }
    

    1.4.3.Barn Repair

    思路:

    首先假设买一块长度为第nn个牛棚-11个牛棚的木板,然后我们可以试着把这块木板分成kk块(也就是切割k1k-1次!),那么最优的肯定是先将两个牛棚之间距离最大的部分割掉,然后割掉第二大的。。。以此类推。
    要特判可用木板数&gt;&gt;牛棚数的情况。

    代码:

    /*
    ID:ssl_zyc2
    TASK:barn1
    LANG:C++
    */	
    
    #include <cstdio>
    #include <algorithm>
    #define N 250
    using namespace std;
    
    int n,m,k,a[N],b[N],sum;
    
    bool cmp(int x,int y)
    {
    	return x>y;
    }
    
    int main()
    {
    	freopen("barn1.in","r",stdin);
    	freopen("barn1.out","w",stdout);
    	scanf("%d%d%d",&n,&m,&k);
    	if (n>=k)
    	{
    		printf("%d\n",k);
    		return 0;
    	}
    	for (int i=1;i<=k;i++)
    	 scanf("%d",&a[i]);
    	sort(a+1,a+1+k);  
    	sum=a[k]-a[1]+1;  //一块木板
    	for (int i=1;i<k;i++)
    	 b[i]=a[i+1]-a[i];  //求出任意两个相邻的牛棚之间的距离
    	sort(b+1,b+k,cmp);
    	for (int i=1;i<n;i++)  //只能切n-1次!!!
    	 sum=sum-b[i]+1;
    	printf("%d\n",sum);
    	return 0;
    }
    

    1.4.5.Prime Cryptarithm

    思路:

    由于每一个“*”只可能是0099中的任意一个数字,那么我们可以枚举乘数里面的五个&quot;&quot;&quot;*&quot;分别是多少,然后就可以推出中间的六个&quot;&quot;&quot;*&quot;的值和答案的四个&quot;&quot;&quot;*&quot;的值。那么久判断每一个值是否合法即可。
    时间复杂度:O(n5)O(n^5)

    代码:

    /*
    ID:ssl_zyc2
    TASK:crypt1
    LANG:C++
    */
    
    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    int n,a,b,ans;
    bool p[11];
    
    bool check(int x,int y)
    {
    	y++;
    	while (x)
    	{
    		if (!p[x%10]) return 0;
    		x/=10;
    		y--;
    		if (!y) return 0;
    	}
    	return 1;
    }
    
    int main()
    {
    	freopen("crypt1.in","r",stdin);
    	freopen("crypt1.out","w",stdout);
    	cin>>n;
    	int x;
    	for (int i=1;i<=n;i++)
    	{
    		cin>>x;
    		p[x]=1;
    	}
    	for (int i=1;i<=9;i++)
    	 if (p[i])
    	  for (int j=0;j<=9;j++)
    	   if (p[j])
    	    for (int k=0;k<=9;k++)
    	     if (p[k])
    	      for (int l=1;l<=9;l++) 
    	       if (p[l])
    	        for (int q=0;q<=9;q++)  //枚举5个*
    	         if (p[q])
    	          if (check((i*100+j*10+k)*l,3))
    	           if (check((i*100+j*10+k)*q,3))  //判断中间的六个*
    	            if (check((i*100+j*10+k)*(l*10+q),4))  //判断积中的四个*
    	             ans++;
    	printf("%d\n",ans);
    	return 0;
    }
    

    1.4.6.Combination Lock

    思路:

    暴力模拟。很简单吧。。。
    小心数组越界。

    代码:

    /*
    ID:ssl_zyc2
    TASK:combo
    LANG:C++
    */
    
    #include <cstdio>
    #define N 120
    using namespace std;
    
    int n,sum,a,b,c,d,e,f;
    bool p[N][N][N];
    
    int main()
    {
    	freopen("combo.in","r",stdin);
    	freopen("combo.out","w",stdout);
    	scanf("%d%d%d%d%d%d%d",&n,&a,&b,&c,&d,&e,&f);
    	for (int i=a-2;i<=a+2;i++)
    	 for (int j=b-2;j<=b+2;j++)
    	  for (int k=c-2;k<=c+2;k++)  //第一个密码
    	   if (!p[(i+n-1)%n+1][(j+n-1)%n+1][(k+n-1)%n+1])
    	   {
    	   	  p[(i+n-1)%n+1][(j+n-1)%n+1][(k+n-1)%n+1]=1;
    	   	  sum++;
    	   }
    	for (int i=d-2;i<=d+2;i++)
    	 for (int j=e-2;j<=e+2;j++)
    	  for (int k=f-2;k<=f+2;k++)  //第二个密码
    	   if (!p[(i+n-1)%n+1][(j+n-1)%n+1][(k+n-1)%n+1])
    	   {
    	   	  p[(i+n-1)%n+1][(j+n-1)%n+1][(k+n-1)%n+1]=1;
    	   	  sum++;
    	   }
    	printf("%d\n",sum);
    	return 0;
    }
    

    1.4.7.Wormholes

    思路:

    有点难度啊。
    由于贝西只能往下走,那么她所在位置的下面第一个虫洞就是会被传走的地方。
    那么设next[i]next[i]表示在ii下面的第一个虫洞(yy坐标要相同,xx坐标严格小于且最近)。然后就深搜,搜出配对的方案后就判断是否成立。成立就记录。

    代码:

    /*
    ID:ssl_zyc2
    TASK:wormhole
    LANG:C++
    */
    
    #include <cstdio>
    using namespace std;
    
    int f[15],next[15],n;
    
    int check()
    {
    	for (int i=1;i<=n;i++)
    	{
    		int u=i;
    		for (int j=1;j<=n;j++)
    		 u=next[f[u]];  //是否死循环
    		if (u) return 1;
    	}
    	return 0;
    }
    
    int dfs(int s)
    {
    	if (s==n/2) return check();  //搜好了
    	int x;
    	for (x=1;x<=n;x++)
    	 if (!f[x]) break;  //没有配对
    	int ans=0;
    	for (int i=1;i<=n;i++)
    	 if (i!=x&&!f[i])
    	 {
    	 	f[x]=i;
    	 	f[i]=x;
    	 	ans+=dfs(s+1);
    	 	f[x]=0;
    	 	f[i]=0;
    	 }
    	return ans;
    }
    
    int main()
    {
    	freopen("wormhole.in","r",stdin);
    	freopen("wormhole.out","w",stdout);
    	scanf("%d",&n);
    	int x[15],y[15];
    	for (int i=1;i<=n;i++)
    	 scanf("%d%d",&x[i],&y[i]);
    	for (int i=1;i<=n;i++)
    	 for (int j=1;j<=n;j++)
    	  if (i!=j)
    	   if (y[i]==y[j]&&x[j]>x[i]&&(!next[i]||x[next[i]]>x[j]))
    	    next[i]=j;
    	printf("%d\n",dfs(0));
    	return 0;
    }
    

    1.4.8.Ski Course Design

    思路:

    由于山峰高度只有100100,那么就可以枚举山峰最矮高度,然后再枚举每个山峰,如果不够或高出那么就计算所需费用。然后将所有费用取最小值即可。

    代码:

    /*
    ID:ssl_zyc2
    TASK:skidesign
    LANG:C++
    */
    
    #include <cstdio>
    #include <algorithm>
    #define N 1010
    using namespace std;
    
    int h[N],sum,n,ans;
    
    int main()
    {
    	freopen("skidesign.in","r",stdin);
    	freopen("skidesign.out","w",stdout);
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++)
    	 scanf("%d",&h[i]);
    	sort(h+1,h+1+n);
    	if (h[n]-h[1]<=17)  //特判,本来就不用
    	{
    		printf("0\n");
    		return 0;
    	}
    	ans=1e9;
    	for (int i=h[1];i<=h[n]-17;i++)  //枚举最低高度
    	{
    		sum=0;
    		for (int j=1;j<=n;j++)  //枚举山峰
    	  	 if (h[j]<i) sum=sum+(i-h[j])*(i-h[j]);
    	   	  else if (h[j]>i+17) sum=sum+(h[j]-i-17)*(h[j]-i-17);
    	   	if (sum<ans) ans=sum;
    	}
    	printf("%d\n",ans);
    	return 0;
    }
    
  • 相关阅读:
    把程序的定义与实现部分用头文件与源文件分开
    简单控件的应用(二)—学生管理系统
    Java基础14
    创建插入符、输出不同效果的文字
    Java基础12
    简单控件的应用(一)—prj计算器
    简单的Win 32 Application
    最简单的音乐播放器
    消息处理初步
    基于MFC,在非客户区与客户区利用CButon类创建button
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998535.html
Copyright © 2011-2022 走看看