zoukankan      html  css  js  c++  java
  • 【USACO2.1】解题报告

    前言

    USACO2.1主要内容是图论。其中有几道题是要用深搜做的。而另外几道题则是利用模拟的方法来完成简单图论。
    总体来说难度还是比较小的,算是最基础的算法吧。
    UASCO:http://train.usaco.org


    2.1.3.The Castle

    题解


    2.1.4.Ordered Fractions

    思路:

    可以枚举分子和分母,然后判断他们的最小公约数是不是11(其实就是判断是否互质)。如果是的话就将这个分数加入到结构体里面,储存三个变量:

    • 分子ZZ
    • 分母MM
    • 这个分数的值numnum(实数类型)

    然后按照分数值排序输出即可。

    代码:

    /*
    ID:ssl_zyc2
    TASK:frac1
    LANG:C++
    */
    
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    int n,sum;
    
    struct node
    {
        int z,m;
        double num;
    }a[160*160+10];
    
    bool cmp(node x,node y)
    {
        return x.num<y.num;
    }
    
    int main()
    {
        scanf("%d",&n);
        a[++sum].z=0;
        a[sum].m=1;
        a[sum].num=0;  //分子为0的唯一情况先打上
        for (int i=1;i<=n;i++)
         for (int j=1;j<=i;j++)
          if (__gcd(i,j)==1)  //互质
          {
          	 a[++sum].z=j;
          	 a[sum].m=i;
          	 a[sum].num=(double)j/(double)i/1.0;
          }
        sort(a+1,a+1+sum,cmp);  //排序
        for (int i=1;i<=sum;i++)
         printf("%d/%d
    ",a[i].z,a[i].m);
        return 0;
    }
    

    2.1.5.Sorting a Three-Valued Sequence

    思路:

    这道题有点恶心。
    读入a[i]a[i],将a[i]a[i]排好序后为b[i]b[i],然后从前往后扫,如果a[i]!=b[i]a[i]!=b[i]就说明这个a[i]a[i]的位置是错误的。那么要分情况。

    1. 先到a[i]a[i]本来应该在的位置,如果这个位置中有为本来应该在a[i]位置的数字,那么就交换两个数字,一次交换就满足了两个数字。
    2. 如果这个位置中没有为本来应该在a[i]位置的数字,那么就随便找一个要到a[i]a[i]位置来的数字交换,一次交换只满足了一个数字。

    模拟即可。

    代码:

    /*
    ID:ssl_zyc2
    TASK:sort3
    LANG:C++
    */
    
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    int n,a[1010],b[1010],cnt;
    bool ok;
    
    int main()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            b[i]=a[i];
        }
        sort(b+1,b+1+n);
        for (int i=1;i<=n;i++)
         if (a[i]!=b[i])  //不相同
         { 
         	ok=false;
         	for (int j=i+1;j<=n;j++)
         	 if (a[i]==b[j]&&a[j]==b[i])   //情况1
         	 {
         	 	swap(a[i],a[j]);
         	 	cnt++;
         	 	ok=true;
         	 	break;
             }
            if (!ok)  //情况2
             for (int j=n;j>i;j--)
              if (a[j]==b[i]) 
              {
              	 swap(a[i],a[j]);
              	 cnt++;
              	 break;
              }
         }
        printf("%d
    ",cnt);
        return 0;
    }
    

    2.1.6.Healthy Holsteins

    思路:

    深搜枚举每一个饲料,判断买或者不买。最终取答案最小值即可。
    当然如果你英勇一点的话就随机选择那些饲料,多随机几次取最有答案。如果运气好的话应该也是可以过的。

    代码:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    int n,m,need[30],sum[30],f[20][30],used[30];
    
    struct node
    {
        int ans;
        int used[30];
    }ans;
    
    bool check(int k)
    {
        for (int i=1;i<=n;i++)
         if (sum[i]<need[i]) return 0;
        if (k<ans.ans) return 1;
        if (k>ans.ans) return 0;  //取最小值
        sort(used+1,used+1+k);
        for (int i=1;i<=k;i++)
         if (used[i]<ans.used[i]) return 1;
         else if (used[i]>ans.used[i]) return 0;
    }
    
    void dfs(int x,int s)
    {
        if (x>m)
        {
            if (check(s))   //成立
            {
                ans.ans=s;
                for (int i=1;i<=s;i++)
                 ans.used[i]=used[i];
                sort(ans.used+1,ans.used+1+s);  //排序
            }
            return;
        }
        dfs(x+1,s);
        used[s+1]=x;
        for (int i=1;i<=n;i++)
         sum[i]+=f[x][i];
        dfs(x+1,s+1);
        used[s+1]=0;
        for (int i=1;i<=n;i++)
         sum[i]-=f[x][i];
    }
    
    int main()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
         scanf("%d",&need[i]);
        scanf("%d",&m);
        for (int i=1;i<=m;i++)
         for (int j=1;j<=n;j++)
          scanf("%d",&f[i][j]);
        ans.ans=1e9;
        dfs(1,0);
        printf("%d",ans.ans);
        for (int i=1;i<=ans.ans;i++)
         printf(" %d",ans.used[i]);
        printf("
    ");
        return 0;
    }
    //我这种方法很麻烦,应该有更简单的方法的。
    

    2.1.7.Hamming Codes

    思路:

    深搜枚举每一位数是00还是11,搜完一个答案后将它和前面的所有答案进行比较,如果都满足要求就记录下这个答案。最后输出时再转换成十进制即可。

    代码:

    /*
    ID:ssl_zyc2
    TASK:hamming
    LANG:C++
    */
    
    #include <cstdio>
    using namespace std;
    
    int n,m,k,ans[70][10],a[10],sum;
    
    void check()
    {
    	for (int i=1;i<=sum;i++)
    	{
    		int cnt=0;
    		for (int j=1;j<=m;j++)
    		 if (a[j]!=ans[i][j]) cnt++;  //不同的位数个数
    		if (cnt<k) return;  //不满足要求
    	} 
    	sum++;
    	for (int i=1;i<=m;i++)
    	 ans[sum][i]=a[i];  //记录答案
    }
    
    void dfs(int x)
    {
    	if (x>m)  //选择完了
    	{
    		check();
    		return;
    	}
    	dfs(x+1);  //这一位是0
    	if (sum>=n) return; 
    	a[x]=1;
    	dfs(x+1);  //这一位是1
    	if (sum>=n) return;
    	a[x]=0;
    }
    
    int main()
    {
    	freopen("hamming.in","r",stdin);
    	freopen("hamming.out","w",stdout);
    	scanf("%d%d%d",&n,&m,&k);
    	sum=1;
    	dfs(1);
    	for (int i=1;i<=n;i++)
    	{
    		int s=0,l=0;
    		for (int j=m;j>=1;j--)
    		{
    			s+=(1<<l)*ans[i][j];  //转换成十进制
    			l++;
    		}
    		if (i%10==1) printf("%d",s);
    		else if (i%10==0) printf(" %d
    ",s);
    		else printf(" %d",s);  //USACO神奇的输出要求
    	}
    	if (n%10) printf("
    ");  //USACO神奇的输出要求(末尾必须换行)
    	return 0;
    }
    
  • 相关阅读:
    telnet发邮件
    怎样接收电子邮件(POP3协议简介)(转载,写的很简洁)
    总结:string,char*,CString,int,WCHAR*之间的相互转换:
    文件查找
    SOAP消息机制简介
    jQuery 万能的选择器 NO.1
    数据库通用操作类
    jQuery (三) 管理jQuery包装集
    WebService Learning
    使用JQuery读取XML文件数据
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998489.html
Copyright © 2011-2022 走看看