hdu5798

官方题解:

考虑去掉abs符号,发现只有相邻两个数的最高位被影响了才会影响abs的符号,所以可以按照最高位不一样的位置分类,之后考虑朴素枚举x从0到2^20,每次的复杂度是O(400),无法通过,考虑优化,第一种方法是用DFS来进行枚举,第二种则是加入记忆化

用dfs枚举简单一点

 1 #include<bits/stdc++.h>
 2
 3 using namespace std;
 4 typedef long long ll;
 5 int d[20],n,mx,ansx;
 6 ll anss,c[20][20];
 7 void dfs(int i,int x,ll s)
 8 {
 9     if (s>anss) return;
10     if (i>mx)
11     {
12         if (s<anss||(s==anss&&x<ansx))
13         {
14             anss=s;
15             ansx=x;
16         }
17         return;
18     }
19     for (d[i]=0; d[i]<=1; d[i]++)
20     {
21         ll ns=s+c[i][i];
22         for (int j=0; j<i; j++)
23             if (d[i]^d[j]) ns-=c[i][j];
24             else ns+=c[i][j];
25         dfs(i+1,x+d[i]*(1<<i),ns);
26     }
27 }
28
29 int work(int a,int b,int h)
30 {
31     if (a<b) swap(a,b);
32     for (int i=h; i>=0; i--)
33         c[h][i]+=((a>>i&1)-(b>>i&1))<<i;
34 }
35
36 int main()
37 {
38     int cas;
39     scanf("%d",&cas);
40     while (cas--)
41     {
42         scanf("%d",&n);
43         int a,b;
44         scanf("%d",&a);
45         memset(c,0,sizeof(c));
46         mx=19;
47         for (int i=1; i<n; i++)
48         {
49             scanf("%d",&b);
50             int h=19;
51             while (h>=0&&!((a>>h&1)^(b>>h&1))) h--;
52             work(a,b,h);
53             a=b;
54         }
55         while (mx>=0&&!c[mx][mx]) mx--;
56         anss=1e18; ansx=0;
57         dfs(0,0,0);
58         printf("%d %lld\n",ansx,anss);
59     }
60 }

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
int d[20],n,mx,ansx;
ll anss,c[20][20];
void dfs(int i,int x,ll s)
{
    if (s>anss) return;
    if (i>mx)
    {
        if (s<anss||(s==anss&&x<ansx))
        {
            anss=s;
            ansx=x;
        }
        return;
    }
    for (d[i]=0; d[i]<=1; d[i]++)
    {
        ll ns=s+c[i][i];
        for (int j=0; j<i; j++)
            if (d[i]^d[j]) ns-=c[i][j];
            else ns+=c[i][j];
        dfs(i+1,x+d[i]*(1<<i),ns);
    }
}

int work(int a,int b,int h)
{
    if (a<b) swap(a,b);
    for (int i=h; i>=0; i--)
        c[h][i]+=((a>>i&1)-(b>>i&1))<<i;
}

int main()
{
    int cas;
    scanf("%d",&cas);
    while (cas--)
    {
        scanf("%d",&n);
        int a,b;
        scanf("%d",&a);
        memset(c,0,sizeof(c));
        mx=19;
        for (int i=1; i<n; i++)
        {
            scanf("%d",&b);
            int h=19;
            while (h>=0&&!((a>>h&1)^(b>>h&1))) h--;
            work(a,b,h);
            a=b;
        }
        while (mx>=0&&!c[mx][mx]) mx--;
        anss=1e18; ansx=0;
        dfs(0,0,0);
        printf("%d %lld\n",ansx,anss);
    }
}
时间: 2024-11-06 12:00:50

hdu5798的相关文章