1. 程式人生 > >演算法訓練(一)

演算法訓練(一)

1.zoj-4049

簡單的程序模擬,大部分情況下可以直接出答案,當進入死迴圈的時候,不難發現,迴圈中所得值會出現重複,因此可視重複為死迴圈的標誌,使用一個bool陣列進行標記即可,程式碼如下:

#include <iostream>

#include<cstring>
using namespace std;

const int N = 10100;
const int Mod = 256;

bool dp[N][257];
struct node {
    char op[4];
    int v, k;
}p[N];

bool check(int pos, int num) 
{
    if (dp[pos][num]) return false;
    else return true;
}

int main() 
{
    int t;
    scanf("%d", &t);
    while (t--) 
    {
        memset(p, 0, sizeof(p));
        memset(dp, false, sizeof(dp));
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) 
        {
            scanf("%s", p[i].op);
            if (strcmp(p[i].op, "add") == 0) scanf("%d", &p[i].v);
            else scanf("%d%d", &p[i].v, &p[i].k);
        }
        int num = 0, pos = 1;
        bool flag = true;
        while (pos <= n && flag) 
        {
            flag = check(pos, num);
            if (!flag) continue;
            dp[pos][num] = true;
            if (strcmp(p[pos].op, "add") == 0) 
            {
                num = (num + p[pos].v) % Mod;
                pos++;
            }
            else if (strcmp(p[pos].op, "beq") == 0) 
            {
                if (num == p[pos].v) pos = p[pos].k;
                else pos++;
            }
            else if (strcmp(p[pos].op, "bne") == 0) 
            {
                if (num != p[pos].v) pos = p[pos].k;
                else pos++;
            }
            else if (strcmp(p[pos].op, "blt") == 0) 
            {
                if (num < p[pos].v) pos = p[pos].k;
                else pos++;
            }
            else 
            {
                if (num > p[pos].v) pos = p[pos].k;
                else pos++;
            }
        }
        if (flag) puts("Yes");
        else puts("No");
    }
    return 0;
}
 

2.zoj-4057

通過分析可得,最短的序列的二進位制位一定是要相同的,這樣最高位異或後皆為0,一定會比序列中最小的值還要小,所以只要求出二進位制位數相同的最多的序列即可,程式碼如下:

#include<cstdio>
#include<cmath>
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
int a[35];
void init()
{
    for (int i = 1; i <= 30; i++)
    {
        a[i] = (int)(pow(2, i));
    }
}
int main()
{
    int t;
    init();
    scanf_s("%d", &t);
    while (t--)
    {

        int n;
        scanf_s("%d", &n);
        int sum[35] = { 0 };
        for (int i = 0; i<n; i++)
        {
            int x;
            scanf_s("%d", &x);
            for (int j = 1; j <= 30; j++)
            {
                if (x<a[j])
                {
                    sum[j]++;
                    break;
                }
            }
        }
        int ans = -1;
        for (int i = 1; i <= 30; i++)
        {
            ans = max(ans, sum[i]);
        }
        printf("%d\n", ans);
    }
    return 0;
}
 

3.zoj-4056

可先畫時間軸,不難發現,整個時間軸其實是由多次迴圈得到的,於是我們可以先求出兩個時間的最小公倍數確定迴圈,因為每次燈泡只維持(v+0.5)s,所以將一個迴圈中的兩個時間的倍數壓進陣列排序去重,燈沒亮的時候要花一次去按燈,迴圈中的算出來後還要跑一次多出來的不在迴圈中的即可,程式碼如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;
#define int long long
vector<long long>V;

int gcd(int a, int b)
{
    if (b == 0)
        return 1;
    else
        return gcd(b, a%b);
}

int main()
{
    int T;
    scanf("%lld", &T);
    while (T--)
    {
        int a, b, c, d, v, t;
        scanf("%lld%lld%lld%lld%lld%lld", &a, &b, &c, &d, &v, &t);
        long long te = gcd(a, c);
        long long lcm = a * c / te;
        V.clear();
        for (int i = 0; i <= lcm; i += a) V.push_back(i);
        for (int i = 0; i <= lcm; i += c) V.push_back(i);
        sort(V.begin(), V.end());
        V.erase(unique(V.begin(), V.end()), V.end());
        int tmp = 0;
        for (int i = 1; i < V.size(); i++)
        {
            if (V[i] - V[i - 1] > v) tmp++;
        }
        long long ans = (t / a) * b + (t / c) * d + b + d - 1;
        long long cur = t / lcm;
        ans = ans - cur * tmp;
        long long la = t % lcm;
        for (int i = 1; V[i] <= la; i++)
        {
            if (V[i] - V[i - 1] > v) ans--;
        }4
        cout << ans << endl;
    }
}