1. 程式人生 > >USACO2.1【bfs,排序,貪心,dfs,位運算】

USACO2.1【bfs,排序,貪心,dfs,位運算】

前言

開始刷USACO的題了。

正題

刷前必備技能:OI常識,bfs,dfs,位運算,基礎貪心,快速排序。

T1:城堡 TheCastleThe Castle

T2:順序的分數 OrderedFractionsOrdered Fractions

題目大意

求最簡分數 ab(a,b<=na,bN)\frac{a}{b}(a,b<=n,a,b\in N) 從小到大輸出。

解題思路

暴力列舉ab,gcd判斷最間,然後排序。

code

// luogu-judger-enable-o2
#include<cstdio> #include<algorithm> using namespace std; int n,tot; struct node{ int a,b; double w; }a[10001]; bool cmp(node x,node y) { return x.w<y.w; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) if(__gcd(i,j)
==1) {a[++tot]=(node){i,j,(double)i/j};}//暴力列舉 sort(a+1,a+1+tot,cmp);//排序 printf("0/1\n"); for(int i=1;i<=tot;i++) printf("%d/%d\n",a[i].a,a[i].b); printf("1/1"); }

T3:三值的排序 SortingaThreeValuedSequenceSorting a Three-Valued Sequence

題目大意

1,2,3構成的序列,要求至少多少次交換可以將其變為升序序列。

解題思路

我們考慮所以放錯位置的數。 如果3放在了1,2的位置上,那麼就一定是需要一次交換的。如果1放在了2的位置或2放在了1的位置,那麼可以選擇1放回去或2放回去,當然我們可以將錯的2和錯的1抵消所以答案就是 wrong3+max{wrong1,wrong2}wrong_3+max\{wrong_1,wrong_2\}

code

#include<cstdio>
#include<algorithm>
using namespace std;
int n,a[1001],s,num[4],fail[4];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
      scanf("%d",&a[i]),num[a[i]]++;
    for(int i=1;i<=num[1]+num[2];i++)
    {
        if(a[i]==3) fail[3]++;//3放錯位置
        if(i<=num[1]&&a[i]==2) fail[2]++;//2放錯位置
        if(i>num[1]&&a[i]==1) fail[1]++;//1放錯位置
    }
    printf("%d",fail[3]+max(fail[1],fail[2]));
}

T4:健康的荷斯坦奶牛 HealthyHolsteinsHealthy Holsteins

題目大意

牛對於v種維生素有不同的需求,每包飼料含有不等量不同的維生素。求需要的最少飼料包數

解題思路

dfs暴搜

code

#include<cstdio>
using namespace std;
int v,n,mins,ans[30],h[30][30],use[30],ne[30],now[30];
bool check()
{
    for(int i=1;i<=v;i++)
      if(now[i]<ne[i]) return false;
    return true;
}
void dfs(int dep,int c)
{
    if(c>=mins||dep>n) return;
    if(check())
    {
        for(int i=1;i<=n;i++)
          ans[i]=use[i];
        mins=c;
    }
    use[dep+1]=1;
    for(int i=1;i<=v;i++)
      now[i]+=h[dep+1][i];
    dfs(dep+1,c+1);
    use[dep+1]=0;
    for(int i=1;i<=v;i++)
      now[i]-=h[dep+1][i];
    dfs(dep+1,c);
}
int main()
{
    scanf("%d",&v);
    for(int i=1;i<=v;i++)
      scanf("%d",&ne[i]);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
      for(int j=1;j<=v;j++)
        scanf("%d",&h[i][j]);
    mins=2147483647;
    dfs(0,0);
    printf("%d ",mins);
    for(int i=1;i<=n;i++)
      if(ans[i]) printf("%d ",i);
}

T5:海明碼 HammingCodesHamming Codes

題目大意

求n個最小的非負整數,要求每個數兩兩之間HammingHamming距離(二進位制位數不相同的個數)。

解題思路

之接暴力過去列舉數,然後aba\bigoplus b後統計1的個數就可以計算距離來判斷。

code

#include<cstdio>
#include<algorithm>
using namespace std;
int n,b,d,now,last,tot,ans[100];
int main()
{
    scanf("%d%d%d",&n,&b,&d);
    n--;
    tot=1;
    printf("0 ");
    ans[1]=0;
    while(n)
    {
        now++;
        bool flag=true;
        for(int i=0;i<=tot;i++)
        {
            if(__builtin_popcount(now^ans[i])<d){
                flag=false;
                break;
            }
        }//是否滿足要求
        if (flag)
        {
            printf("%d ",now);
            ans[++tot]=now;
            if(tot%10==0) printf("\n");
            n--;
        }
    }
}