AHU_ACM_2014(个人积分赛第三场)

来源:互联网 发布:玉观音知乎 编辑:程序博客网 时间:2024/06/05 07:38

地址:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=38440#overview

1.poj1306/Combination

题意:计算组合数,利用C(n,m)=C(n-1,m-1)+C(n-1,m)公式计算。(C(n,0) = 1!!!) 先打表,计算所有的值,然后查表得到。水题

#include<iostream>using namespace std;int main(){    __int64 c[101][101] = {0};    for (int i = 1; i < 101; i++){        c[i][0] = 1;        c[i][i] = 1;    }    for (int i = 2; i < 101; i++)    for (int j = 1; j < i; j++)    c[i][j] = c[i-1][j] + c[i-1][j-1];        int n,m;    while(cin>> n >> m && n*m != 0)    cout << n <<" things taken " << m <<" at a time is " << c[n][m] << " exactly." << endl;}

2.poj1742/Coins

题意:有一定数目的钱币,每种钱币又有很多张。问一共能组成多少种方案?
大体就是多重背包,之前用二进制优化的背包因为时间复杂度不能用,新学的加了个u数组判断每次一种钱币是否用尽。中度难度。ps:第一个注释掉的程序对输入数据有点小问题。。。

/*#include<iostream>using namespace std;int main(){    int n,m;    int a[10000];    int v[10000];    while(cin >> n >> m && n*m != 0){              for (int i = 0; i < n; i++){                  cin >> a[i];              }              for (int i = 0; i < n; i++){                  cin >> v[i];              }              int s = n;              int sum = 0;                            for (int i = 0; i < n; i++){                  int k = 1;                  while(a[i] - k*2 + 1 > 0){                             a[s] = k;                             v[s] = v[i] * k;                             k = k << 1;                             s++;                  }                  a[s] = a[i] - k + 1;                  v[s] = v[i] * a[s];                  s++;              }                            bool f[100000];              for (int i = 1; i <= m; i++)              f[i] = false;              f[0] = true;                            for (int i = n; i < s; i++)              for (int j = m; j >= v[i]; j--){                  if (f[j - v[i]] && !f[j]){                          f[j] = true;                          sum++;                  }              }              cout << sum << endl;    }}
#include<iostream>#include<cstring>using namespace std;int main(){    int n,m;    int a[101];    int v[101];    while(cin >> n >> m && n*m != 0){              for (int i = 0; i < n; i++){                  cin >> v[i];              }              for (int i = 0; i < n; i++){                  cin >> a[i];              }              int sum = 0;              bool f[100001];              memset(f,0,sizeof(f));              f[0] = true;              int u[100001];              for (int i = 0; i < n; i++){                  memset(u,0,sizeof(u));                  for (int j = v[i]; j < m+1; j++){                      if (f[j - v[i]] && !f[j]  && u[j - v[i]] + 1 <= a[i]){                              f[j] = true;                              u[j] = u[j - v[i]] + 1;                              sum++;                      }                    }                }                cout << sum << endl;    }}

3.hdu1686/Oulipo

题意:单纯的字符串匹配

裸kmp算法,只不过用cinout就会超时啊 用scanf和printf就93ms。。。纠结啊

#include<iostream>#include<cstring>using namespace std;int test;char a[10001];char b[1000001];int p[10001];int la,lb;void kmp(){    int j = -1;    p[0] = -1;    for (int i = 1; i < la; i++){        while(j >= 0 && a[j+1]!=a[i]) j = p[j];        if (a[j+1] == a[i]) j++;        p[i] = j;    }    j = -1;    int ans = 0;    for (int i = 0; i < lb; i++){        while(j >= 0 && a[j+1] != b[i]) j = p[j];        if (a[j+1] == b[i]) j++;        if (j == la-1) ans++;    }    cout << ans <<endl;}int main(){    cin >> test;    while(test--){        cin >> a;        cin >> b;        la = strlen(a);        lb = strlen(b);        kmp();    }}

4.hdu1213/How many tables?

题意:在一场聚会中,有n个人,有m对相互认识。如果a认识b,b认识c,那么a认识c。现要求认识人坐一桌。问要多少桌子?

利用并查集数据结构。水题

#include<iostream>using namespace std;int fa[10000];int test;int find(int x){    if (x == fa[x]) return x;    else{        return find(fa[x]);    }}bool nort(int x, int y){    int a = find(x);    int b = find(y);    if (a == b) return false;    fa[b] = a;    return true;}int main(){    cin >> test ;    while(test--){        int n,m,x,y,sum = 0;        cin >> n >> m;        for (int i = 0; i <= n; i++)        fa[i] = i;        for (int i = 0; i < m; i++){            cin >> x >> y;            if (nort(x,y)) sum++;        }        cout << n - sum << endl;    }}

5.hdu3863/No Gambling

题意:先手横着连蓝色,后手竖着连俩红色。最后谁连的最多谁赢

咕~~(╯﹏╰)b,博弈吧,先手赢。相互阻挠,因为对称的阻挠相等。显然蓝色可以连的多。

#include<iostream>using namespace std;int n;int main(){    while(cin >> n && n != -1)    cout <<"I bet on Oregon Maple~\n";}

6.poj3660/Cow Contest

题意:给出奶牛的胜负关系,能确定多少只牛的排名

floyd算法,判断一只牛只要赢的次数和输的次数总和等于n-1即能确定排名

#include<iostream>using namespace std;int n,m,x,y;bool a[101][101];int ans = 0;int main(){    cin >> n >> m;    for (int i = 0; i < m; i++){        cin >> x >> y;        a[x][y] = 1;    }    for (int k = 1; k <= n; k++)    for (int i = 1; i <= n; i++)    for (int j = 1; j <= n; j++)    if ( i != k && j != k && i!= j && a[i][k] && a[k][j])        a[i][j] = 1;    for (int i = 1; i <= n; i++){        int sum = 0;        for (int j = 1; j <= n; j++)        if (a[i][j]  || a[j][i]) sum++;        if (sum == n-1) ans++;    }    cout << ans <<endl;}

7.CodeForces 330A/Cakeminator

题意:有草莓的行和列不能切,问能切下多少蛋糕

忘了公式的名字了 总之是统计完行和列后用 : a并b =  a + b - a交b

#include<iostream>using namespace std;int main(){    int n,m;    int cow = 0;    int row = 0;    char a[101][101];    cin >>n >> m;    for (int i = 0; i < n; i++)    for (int j = 0; j < m; j++)    cin >>a[i][j];    for (int i = 0; i < n; i++){        bool v = true;        for (int j = 0; j <m; j++)        if (a[i][j] == 'S'){            v = false;            break;        }        if (v) row++;    }    for (int i = 0; i < m; i++){        bool v = true;        for (int j = 0; j <n; j++)        if (a[j][i] == 'S'){            v = false;            break;        }        if (v) cow++;    }    cout << cow* n + row * m - cow * row <<endl;}

8.CodeForces 330B/Road Construction

题意:给出n座城市和m条不能建的路,接下来是哪两座城市不能建路,输出最少建多少条路能使得从任意一座城市到另一座城市不超过两条路,并输出方案(任意方案即可)
首先,注意到m<n/2,那么必然存在一个点使得它可以到任意节点(取极端条件验证),那么找出这个点即可。条数必然为n-1
#include<iostream>using namespace std;int main(){    int n,m;    int x,y;    bool v[1001]={0};    cin >> n >> m;    for (int i = 0; i < m; i++){        cin >> x >> y;        v[x] = v[y] = true;    }    int k;    for (k = 1; k <= n; k++)    if (!v[k]) break;    cout << n -1 << endl;    for (int i = 1; i <= n; i++)    if (i != k) cout << i << " " << k <<endl;}

9.CodeForces331A/Oh Sweet Beaverette

题意:约会逛小树林,要去砍树林,但树林其实就是一排树。。。每棵树有魅力值,要求现在保留下的树林两端魅力值相等,且最大,而且最少两棵树。第一行输出总魅力值和砍多少树,接下来输出砍哪些树。

这题。。。暴无语,再最小值定义上卡了好久。。。原来是-2000000000,不行,结果-2000000010就通了。。。这道题就是找区间最大和的问题。

#include<iostream>#include<cstring>#include <map>using namespace std;int a[300010];__int64  f[300010];int b[300010];map <int,int> v;int main(){    int n,m,key;    __int64 maxn = -2000000010;    cin >> n;    for (int i = 1; i <= n; i++)    cin >> a[i];    memset(f,0,sizeof(f));    for (int i = 1; i <= n; i++){        if (a[i] >= 0) f[i] = f[i-1] +a[i];        else f[i] = f[i-1];        if (!v[a[i]]) v[a[i]] = i;        else{            if (maxn < f[i-1] - f[v[a[i]]] + 2*a[i]) {                maxn = f[i-1] - f[v[a[i]]] + 2*a[i];                key = i;            }        }    }    int sum = 0;    for (int i = 1; i < v[a[key]]; i++){        b[sum++] = i;    }    for (int i = v[a[key]]+1; i< key; i++){        if (a[i] < 0) b[sum++] = i;    }    for (int i = key + 1; i <= n; i++){        b[sum++] = i;    }    cout << maxn << " " << sum << endl;    for (int i = 0; i < sum - 1; i++)    cout <<b[i] << " ";    if (sum) cout << b[sum -1] << endl;}



0 0
原创粉丝点击