状态压缩!

人生中首次写状压DP,不像ouuan大佬那样一遍AC,而是反复调了好久…而且代码还极丑陋…

 

题目大意:给您一张无向图,带点权。要求值最大的曼哈顿路径的值,并计数。

 

一条曼哈顿路径的值:所有点权之和,加相邻两点的乘积,加相邻三点的乘积(如果第一点和第三点连通)。

 

数据范围13,显然是状压DP。

 

状态表示:(1<<j)为1表示此点被访问过,为0则未访问过。
那么f[i][j][k]表示状态为i,最后一个点为j,倒数第二个点为k的最大值。num[i][j][k]则表示方案数。
DP的时候直接暴力循环就行了。

 

需要注意的两点:

 

  • 路径数要>>1,因为正反走只算一条线。
  • 需要特判各种状态行不行。这个是重点,巨烦人……

 

下面放上我丑陋的代码和标程,附带对拍器(对拍真好用)。

  1 #include <cstdio>
  2 #include <cstring>
  3 using namespace std;
  4 typedef long long LL;
  5 inline int read()
  6 {
  7     int ans=0;char ch=getchar();
  8     while(ch<'0'||ch>'9')
  9         ch=getchar();
 10     while(ch>='0'&&ch<='9')
 11         ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
 12     return ans;
 13 }
 14 int chart[14][14],V[14],n;
 15 LL f[1<<13][14][14],num[1<<13][14][14];
 16 bool check(int i,int j,int k)
 17 {
 18     return chart[j][k]&&((1<<j)&i)&&((1<<k)&i);
 19 }
 20 int cal(int x)
 21 {
 22     int a[14],ans=0;
 23     for(int i=0;i<14;i++) a[i]=bool(x&(1<<i));
 24     for(int i=13;i>=0;i--) ans=ans*10+a[i];
 25     return ans;
 26 }
 27 /**
 28 2
 29 3 3
 30 2 2 2
 31 1 2
 32 2 3
 33 3 1
 34 */
 35 void solve(int i,int j,int k)
 36 {
 37     //printf("solve:%d %d %d  %d   ",cal(i),j,k,f[i][j][k]);
 38     int t=0,ii=i;
 39     while(ii)
 40         t+=(ii&1),ii>>=1;
 41     if(t==1) return;
 42     if(t==2)
 43     {
 44         num[i][j][k]=1;
 45         f[i][j][k]=V[j]+V[k]+V[j]*V[k];
 46         //printf("%d\n",f[i][j][k]);
 47         return;
 48     }
 49     for(int x=0;x<n;x++)
 50     {
 51         if(((1<<x)&i)&&chart[x][k]&&(x!=j)&&f[i^(1<<j)][k][x])
 52         {
 53             int temp = f[i^(1<<j)][k][x] + V[j] + V[j]*V[k] + (chart[x][j])*V[x]*V[k]*V[j];
 54             //printf("x=%d temp:%d=%d+%d+%d+%d   ",x,temp,f[i^(1<<j)][k][x],V[j],V[j]*V[k],(chart[x][j])*V[x]*V[k]*V[j]);
 55             if(temp>f[i][j][k])
 56             {
 57                 f[i][j][k]=temp;
 58                 num[i][j][k]=num[i^(1<<j)][k][x];
 59             }
 60             else if(temp==f[i][j][k])
 61                 num[i][j][k]+=num[i^(1<<j)][k][x];
 62         }
 63     }
 64     //printf("%d\n",f[i][j][k]);
 65     return;
 66 }
 67 int main()
 68 {
 69     //freopen("my.in","r",stdin);
 70     //freopen("my.out","w",stdout);
 71     int T = read();
 72     while(T--)
 73     {
 74         n=read();
 75         int m=read(),x,y;
 76         int N = 1<<n;
 77         for(int i=1;i<=n;i++) V[i-1]=read();
 78         for(int i=1;i<=m;i++)
 79         {
 80             x=read();y=read();
 81             x--;y--;
 82             chart[x][y]=chart[y][x]=1;
 83         }
 84         if(n==1)
 85         {
 86             printf("%d 1\n",V[0]);
 87             continue;
 88         }
 89         ///初始化
 90         for(int i=0;i<n;i++)
 91         {
 92             f[1<<i][i][0]=V[i];
 93             num[1<<i][i][0]=1;
 94         }
 95         ///DP
 96         for(int i=1;i<N;i++)
 97         {
 98             for(int j=0;j<n;j++)
 99             {
100                 for(int k=0;k<n;k++)
101                 {
102                     if(check(i,j,k)) solve(i,j,k);
103                 }
104             }
105         }
106         ///统计答案
107         LL ans=0,ans2=0;
108         for(int j=0;j<n;j++)
109         {
110             for(int k=0;k<n;k++)
111             {
112                 if(ans<f[N-1][j][k])
113                 {
114                     ans=f[N-1][j][k];
115                     ans2=num[N-1][j][k];
116                 }
117                 else if(ans==f[N-1][j][k])
118                 {
119                     ans2+=num[N-1][j][k];
120                 }
121             }
122         }
123         printf("%I64d %I64d\n",ans,ans2>>1);
124         ///
125         memset(f,0,sizeof(f));
126         memset(num,0,sizeof(num));
127         memset(chart,0,sizeof(chart));
128     }
129     return 0;
130 }
AC代码

相关文章:

  • 2021-11-03
  • 2021-06-19
  • 2022-02-04
  • 2022-02-07
  • 2021-06-03
  • 2022-12-23
  • 2021-08-29
  • 2021-08-11
猜你喜欢
  • 2022-02-28
  • 2021-08-08
  • 2021-11-26
  • 2022-12-23
  • 2021-11-29
  • 2022-12-23
相关资源
相似解决方案