71 24 95 56 54 85 50 74 94 28 92 96 23 71 10 23 61 31 30 46 64 33 32 95 89 78 78 11 55 20 11 98 54 81 43 39 97 12 15 79 99 58 10 13 79 83 65 34 17 85 59 61 12 58 97 40 63 97 85 66 90 33 49 78 79 30 16 34 88 54 39 26 80 21 32 71 89 63 39 52 90 14 89 49 66 33 19 45 61 31 29 84 98 58 36 53 35 33 88 90 19 23 76 23 76 77 27 25 42 70 36 35 91 17 79 43 33 85 33 59 47 46 63 75 98 96 55 75 88 10 57 85 71 34 10 59 84 45 29 34 43 46 75 28 47 63 48 16 19 62 57 91 85 89 70 80 30 19 38 14 61 35 36 20 38 18 89 64 63 88 83 45 46 89 53 83 59 48 45 87 98 21 15 95 24 35 79 35 55 66 91 95 86 87 94 15 84 42 88 83 64 50 22 99 13 32 85 12 43 39 41 23 35 97 54 98 18 85 84 61 77 96 49 38 75 95 16 71 22 14 18 72 97 94 43 18 59 78 33 80 68 59 26 94 78 87 78 92 59 83 26 88 91 91 34 84 53 98 83 49 60 11 55 17 51 75 29 80 14 79 15 18 94 39 69 24 93 41 66 64 88 82 21 56 16 41 57 74 51 79 49 15 59 21 37 27 78 41 38 82 19 62 54 91 47 29 38 67 52 92 81 99 11 27 31 62 32 97 42 93 43 79 88 44 54 48
572 683 2096 2755
未优化的:300ms
#include <iostream> #include <sstream> #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <queue> #include <algorithm> #include <map> #include <cmath> #include <iomanip> #define INF 99999999 typedef long long LL; using namespace std; const int MAX=1597+10; int n,nowsize,lastsize; int now[MAX],last[MAX]; int dp[MAX],temp[MAX],ans[MAX]; int w[16][16]; char s[MAX]; void dfs(int id,int k,int p,int sum){ if(k>=n){now[++nowsize]=p;ans[nowsize]=sum;return;} dfs(id,k+2,p|(1<<k),sum+w[id][k]); dfs(id,k+1,p,sum); } void DP(){ for(int k=1;k<=n;++k){ nowsize=0; dfs(k,0,0,0); for(int i=1;i<=nowsize;++i)dp[i]=0; for(int i=1;i<=nowsize;++i){ for(int j=1;j<=lastsize;++j){ if(now[i] & last[j])continue; if(now[i] & (last[j]<<1))continue; if(now[i] & (last[j]>>1))continue; dp[i]=max(dp[i],temp[j]+ans[i]); } } for(int i=1;i<=nowsize;++i)temp[i]=dp[i]; for(int i=1;i<=nowsize;++i)last[i]=now[i]; lastsize=nowsize; } } int main(){ int k; while(gets(s)){ k=1; do{ n=0; stringstream ss(s); while(ss>>w[k][n])++n; gets(s); if(s[0] == '\0')break; ++k; }while(true); n=k; temp[1]=last[1]=0; lastsize=1; DP(); int sum=0; for(int i=1;i<=lastsize;++i)sum=max(sum,temp[i]); printf("%d\n",sum); } return 0; }优化后的:31ms
/*优化分析: 由于该正方形除了相邻之间不能选之外没有其他约束条件 所以每一行的状态以及状态数其实是一样的,所以就不用1~n行每次都求该行的状态以及状态数 只要求一边即可,然后把状态以及状态数保存好并且对于状态i,用邻接矩阵储存和状态i共存的状态 然后对于第k行第i个状态,只需要采用邻接表枚举和i共存的状态来求dp[k][i]即可 */ #include <iostream> #include <sstream> #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <queue> #include <algorithm> #include <map> #include <cmath> #include <iomanip> #define INF 99999999 typedef long long LL; using namespace std; const int MAX=1597+10; int n,nowsize,size; int dp[MAX],temp[MAX],ans[MAX],now[MAX]; int w[16][16],head[MAX]; char s[MAX]; struct Edge{ int v,next; Edge(){} Edge(int V,int NEXT):v(V),next(NEXT){} }edge[30000]; void Init(int N){ n=N; memset(dp,0,sizeof dp); memset(temp,0,sizeof temp); memset(head,-1,sizeof head); size=nowsize=0; } void InsertEdge(int u,int v){ edge[size]=Edge(v,head[u]); head[u]=size++; } void dfs(int k,int p){ if(k>=n){now[++nowsize]=p;return;} dfs(k+2,p|(1<<k)); dfs(k+1,p); } int cal(int k,int p){ int sum=0; for(int i=0;i<15;++i){ if(p & (1<<i))sum+=w[k][i]; } return sum; } void DP(){ dfs(0,0); for(int i=1;i<=nowsize;++i){//此处是优化,采用邻接表储存状态 for(int j=i+1;j<=nowsize;++j){ if(now[i] & now[j])continue; if(now[i] & (now[j]<<1))continue; if(now[i] & (now[j]>>1))continue; InsertEdge(i,j); InsertEdge(j,i); } } for(int k=1;k<=n;++k){ for(int i=1;i<=nowsize;++i){ ans[i]=cal(k,now[i]); for(int j=head[i];j != -1;j=edge[j].next){ dp[i]=max(dp[i],temp[edge[j].v]+ans[i]); } } for(int i=1;i<=nowsize;++i)temp[i]=dp[i],dp[i]=0; } } int main(){ int k; while(gets(s)){ k=1; do{ n=0; stringstream ss(s); while(ss>>w[k][n])++n; gets(s); if(s[0] == '\0')break; ++k; }while(true); Init(k); DP(); int sum=0; for(int i=1;i<=nowsize;++i)sum=max(sum,temp[i]); printf("%d\n",sum); } return 0; }