HDU 4395 D-mail

这就是多校赛的水题了。。。

简单dp放大10000倍,然后左移200000(0.1 *200 *10000)就可以了。。

#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <bitset>
using namespace std;
const int M = 210;
const int N = 220000;
const double eps = 1e-8;
int a[M];
int dp[N];
int main()
{
    int T;
    scanf("%d", &T);
    while(T --)
    {
        int num;
        double testfin;
        scanf("%lf%d", &testfin , &num);
        int fin;
        if(testfin > 0)
        {
            fin = testfin * 10000 + eps;
        }
        else
        {
            fin = testfin * 10000 - eps;
        }
        double test;
        for(int i = 1 ; i <= num ; ++ i)
        {
            scanf("%lf", &test);
            if(test > 0)
            {
                a[i] = test * 10000 + eps;
            }
            else
            {
                a[i] = test * 10000 - eps;
            }
        }
        sort(a + 1 , a + num + 1);
        memset(dp , 0 , sizeof(dp));
        dp[200000] = 1;
        for(int i = 1 ; i <= num ; ++ i)
        {
            if(a[i] > 0)
            {
                for(int j = 220000 - 1 ; j >= a[i] ; -- j)
                {
                    if(dp[j - a[i]])
                    {
                        dp[j] = 1;
                    }
                }
            }
            else
            {
                for(int j = -a[i]; j <= 220000 - 1; ++ j)
                {
                    if(dp[j])
                    {
                        dp[j + a[i]] = 1;
                    }
                }
            }
        }
        int left;
        int right;
        for(left = fin + 200000, right = fin + 200000 ; ; left -- , right ++)
        {
            if(dp[left] && left >= 0)
            {
                printf("%.4lf\n", (left - 200000.0) / 10000);
                break;
            }
            else if(dp[right] && right < 220000)
            {
                printf("%.4lf\n", (right - 200000.0) / 10000);
                break;
            }
        }
    }
    return 0;
}

然后下面是bitset版的,感觉bitset是一个很好的模拟工具。。。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <bitset>
using namespace std;
const double eps = 1e-8;
const int N = 210;
int a[N];
bitset<220000>dp;
int main()
{
    int T;
    scanf("%d", &T);
    while(T --)
    {
        int num;
        double testfin;
        int fin;
        scanf("%lf%d", &testfin, &num);
        if(testfin > 0)
        {
            fin = testfin * 10000 + eps;
        }
        else
        {
            fin = testfin * 10000 - eps;
        }
        double test;
        for(int i = 1 ; i <= num ; ++ i)
        {
            scanf("%lf", &test);
            if(test > 0)
            {
                a[i] = test * 10000 + eps;
            }
            else
            {
                a[i] = test * 10000 - eps;
            }
        }
        sort(a + 1 ,a + num + 1);
        dp.reset();
        dp.set(200000);
        for(int i = 1 ;i <= num ; ++ i)
        {
            if(a[i] > 0)
            {
                dp = dp | (dp << a[i]);
            }
            else
            {
                dp = dp | (dp >> (- a[i]));
            }
        }
        int left, right;
        for(left = 200000 + fin, right = 200000 + fin ; ; left-- ,right ++)
        {
            if(left >= 0 && dp[left])
            {
                printf("%.4lf\n", (left - 200000.0) / 10000);
                break;
            }
            else if(right < 220000 && dp[right])
            {
                printf("%.4lf\n", (right - 200000.0) / 10000);
                break;
            }
        }
    }
    return 0;
}

真是又快又好。。。。

你可能感兴趣的:(dp,HDU,多校)