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;
    }
    
  • 相关阅读:
    CF1202F You Are Given Some Letters...
    CF1178E Archaeology
    PTA (Advanced Level) 1005 Spell It Right
    PTA (Advanced Level) 1004 Counting Leaves
    Qt5——从零开始的Hello World教程(Qt Creator)
    PTA (Advanced Level) 1003 Emergency
    PTA (Advanced Level) 1002 A+B for Polynomials
    HDU 1272 小希的迷宫
    FZU 2150 Fire Game
    HihoCoder
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998489.html
Copyright © 2011-2022 走看看