标签:style blog color io os for sp div 问题
比赛的时候想的是把n个n个的题目进行状压 但这样不能讲究顺序,当时精神面貌也不好,真是挫死了
其实此题的另一个角度就是一个n个数的排列,如果我对n个人进行状压,外面套一个按题目循序渐进的大循环,那么,在当前做第i个题目,前i-1个题目已经做完,然后做完的人的状态为j, j可能是1110 1101 1011什么的(假设已经做了三道题),因为我这样就可以只管状态而不管顺序了,我只取这种状态下的最大值,他究竟是怎么个顺序排列我不用管
到此。。。好像问题就没有什么问题了,这种做法重复 m/n次最后把剩余的再跑一下就可以了,因为每次考虑第i个题的时候 只和i-1有关,则用个滚动数组即可,比较麻烦的是每次要清空,只能说空间和时间不可兼得啊
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; double A[11][1010]; int n,m; double dp[2][1<<11]; int main() { int t,kase=0; scanf("%d",&t); while (t--) { scanf("%d%d",&n,&m); for (int i=0;i<n;i++){ for (int j=0;j<m;j++) scanf("%lf",&A[i][j]); } int ALL=1<<n; for (int i=0;i<=ALL;i++){ dp[0][i]=dp[1][i]=0; } for (int i=0;i<n;i++){ dp[0][1<<i]=A[i][0]; } int p=0; double ans=0; for (int i=1;i<m;i++){ p^=1; for (int j=0;j<=ALL;j++) dp[p][j]=0; for (int j=0;j<ALL;j++){ if (dp[p^1][j]==0) continue; for (int k=0;k<n;k++){ if ((1<<k)&j) continue; int nt=(1<<k)|j; if (nt==ALL-1) nt=0; dp[p][nt]=max(dp[p][nt],dp[p^1][j]+A[k][i]); if (i==m-1) ans=max(ans,dp[p][nt]); } } } printf("Case #%d: %.5lf\n",++kase,ans); } }
标签:style blog color io os for sp div 问题
原文地址:http://www.cnblogs.com/kkrisen/p/4001149.html