UVA - 1354(指针结点的联合方法 || 高效算法复杂度未算出)
2014-10-10 18:35
459 查看
指针结点联合,即每个指针指向一个实际node,联合申请一个新node,并用一个新指针代表它;
下面为高效算法;
用到子集的枚举技巧,node【i】里存的为所有子树姿态下的最优长度;
由于使用
#include<cstdio> #include<cstring> #include<cctype> #include<queue> #include <vector> #include <iostream> using namespace std; const int maxn = 7; typedef struct node *pointer; struct node{ double weight,leftw,rightw,zhong; node *left,*right; node():left(NULL),right(NULL){} }; int n; double w[maxn],r; double res=-1; double cal_wei(pointer root,int floor){ if(root->left==NULL&&root->right==NULL){ root->leftw=root->rightw=0; return root->weight; } root->leftw=cal_wei(root->left,floor+1); root->rightw=cal_wei(root->right,floor+1); return root->leftw+root->rightw; } double Min,Max; void cal_posi(pointer root){ if(root->left==NULL&&root->right==NULL){ return ; } root->left->zhong=root->zhong-root->rightw/(root->rightw+root->leftw); root->right->zhong=root->leftw/(root->rightw+root->leftw)+root->zhong; Max=max(Max,root->right->zhong); Min=min(Min,root->left->zhong); cal_posi(root->left); cal_posi(root->right); } void dfs(int num,vector<pointer>& now){ if(num==1){ cal_wei(now[0],0); now[0]->zhong=0; Min=10000; Max=-10000; cal_posi(now[0]); if(Max-Min>=0&&Max-Min<=r){ res=max(res,Max-Min); } return ; } <pre name="code" class="html">//对本题而言,此解为朴素算法; for(int i=0;i<num;i++) for(int j=0;j<num;j++) if(i!=j){ //最坏复杂度分析, (6*5)*(5*4)*(4*3)*(3*2)*(2*1)*6*10*2 = 10368000; vector<pointer> next; // 临时变量的位置特别重要;该句子放在循环外将导致每次没有消除dfs影响 pointer x=now[i],y=now[j]; for(int k=0;k<num;k++) if(k!=i&&k!=j) next.push_back(now[k]); pointer temp=new node(); temp->weight=-1; temp->left=x; temp->right=y; next.push_back(temp); dfs(num-1,next); } } int main() { int T; scanf("%d",&T); while(T--){ scanf("%lf %d",&r,&n); vector<pointer> ans; double x; for(int i=1;i<=n;i++){ scanf("%lf",&x); pointer temp=new node(); temp->weight=x; ans.push_back(temp); } if(n==1) { double t=0; printf("%.9lf\n",t); continue; } res=-1000; dfs(n,ans); if(res==-1000) printf("-1\n"); else printf("%.9lf\n",res); } return 0; }
下面为高效算法;
用到子集的枚举技巧,node【i】里存的为所有子树姿态下的最优长度;
由于使用
#include <stdio.h> #include <string.h> #include <vector> #define INF 0x3f3f3f3f #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) using namespace std; const int N = 6; const int MAXN = (1<<N); int t, n, i, j, vis[MAXN]; double w , sumw[MAXN], r; struct Node { double l, r; Node() {} Node(double ll, double rr) {l = ll; r = rr;} }; vector<Node> node[MAXN]; int bitcount(int x) { if (x == 0) return 0; return bitcount(x/2) + (x&1); } void dfs(int s) { if (vis[s]) return; vis[s] = 1; if (bitcount(s) == 1) { node[s].push_back(Node(0, 0)); return; } for (int l = (s - 1)&s ; l > 0; l = (l - 1)&s) { //非连续1(如11001)的子集枚举方式,循环量(2^(bitcount(s)-2)) int r = s^l; dfs(l); dfs(r); for (int i = 0; i < node[l].size(); i++) { for (int j = 0; j < node[r].size(); j++) { double ll =min(-sumw[r] / (sumw[l] + sumw[r]) + node[l][i].l,sumw[l] / (sumw[l] + sumw[r]) + node[r][j].l); double rr =max(sumw[l] / (sumw[l] + sumw[r]) + node[r][j].r,-sumw[r] / (sumw[l] + sumw[r]) + node[l][i].r); node[s].push_back(Node(ll, rr)); } } } } void solve() { double ans = -1; int s = (1<<n) - 1; dfs(s); //printf("%d***\n",node[s].size()); node[s].size()代表所有可能的子树的左右最大值或最小值; for (int i = 0; i < node[s].size(); i++) { if (node[s][i].r - node[s][i].l < r) { if (node[s][i].r - node[s][i].l > ans) ans = node[s][i].r - node[s][i].l; } } if (ans == -1) printf("-1\n"); else printf("%.10lf\n", ans); } int main() { scanf("%d", &t); while (t--) { memset(vis, 0, sizeof(vis)); memset(node, 0, sizeof(node)); scanf("%lf%d", &r, &n); for (i = 0; i < n; i++) scanf("%lf", &w[i]); for (i = 0; i < (1<<n); i++) { sumw[i] = 0; for (j = 0; j < n; j++) { if (i&(1<<j)) sumw[i] += w[j]; } } //计算每个子集的重量 solve(); } return 0; }
相关文章推荐
- 时间复杂度算法分析有方法(摘)
- 复杂指针解读方法(待总结)
- 高效算法设计专项:UVa 10827
- 【算法复杂度分析之主方法】
- 【算法复杂度分析之主方法】
- 复杂的指针声明的两种解读方法
- 时间复杂度为O(1)的删除链表结点方法
- 高效算法设计专项:UVa 11054
- 高效算法设计专项:UVa 10535
- C++学习笔记2--函数重载 复杂的数据 内存对齐 指针数组 结构与指针 传值传址传引用 联合枚举类型别名
- 算法题14 删除链表结点(时间复杂度为O(1)))
- [译】顺时针分析规则 —— 一种针对复杂变量声明的分析的方法(尤其是指针类型)
- 算法导论-18.2-5-B树叶结点无指针
- 高效算法设计专项:UVa 11572
- [译】顺时针分析规则 —— 一种针对复杂变量声明的分析的方法(尤其是指针类型)
- 一种高效算法---振动测量中振幅的计算方法
- 时间复杂度为O(1)的删除链表结点方法
- 高效算法设计专项:UVa 10391
- (学习个输出方法)POJ 1929 Calories from Fat(没啥算法,就是比较复杂还有个输出问题)
- 009实现一个算法来删除单链表中的一个结点,只给出指向那个结点的指针(keep it up)