UVa-10618 Tango Tango Insurrection&& UVa-1627 Team them up!
来源:互联网 发布:网络情歌对唱大全 编辑:程序博客网 时间:2024/05/22 15:43
10618
题意繁复,见紫书P291
本题条件比较复杂,是情况比较多的多维dp,个人认为难点在处理各阶段关系上。
看了紫书详细的解释,将各状态下的决策结果通过构造函数计算出来即可。记录一下,以后温习直接翻书。
#include <algorithm>#include <iostream>#include <sstream>#include <cstring>#include <cstdlib>#include <string>#include <vector>#include <cstdio>#include <cmath>#include <queue>#include <stack>#include <map>#include <set>using namespace std;#define INF 0x3f3f3f3fconst int N=100005;const int mod=1e9+7;const int UP=0;const int LEFT=1;const int RIGHT=2;const int DOWN=3;int action[75][4][4][3],d[75][4][4][3];char seq[75],pos[256],footch[]=".LR";int energy(int a,int b) { if (a==b) { return 3; } if (a+b==3) { return 7; } return 5;}int energy(int i,int a,int b,int s,int f,int t,int& ta,int &tb) { ta=a;tb=b; if (f==1) { ta=t; } else if (f==2) tb=t; if (ta==tb) return -1; if (ta==RIGHT&&tb==LEFT) return -1; if (a==RIGHT&&tb!=b) return -1; if (b==LEFT&&ta!=a) return -1; int e; if (f==0) e=0; else if (f!=s) e=1; else { if (f==1) e=energy(a, ta); else e=energy(b, tb); } return e;}void update(int i,int a,int b,int s,int f,int t) { int ta,tb; int e=energy(i,a,b,s,f,t,ta,tb); if (e<0) return; int cost=d[i+1][ta][tb][f]+e; int& ans=d[i][a][b][s]; if (cost<ans) { ans=cost; action[i][a][b][s]=f*4+t; }}int main() { pos['U']=0;pos['L']=1; pos['R']=2;pos['D']=3; while (scanf("%s",seq)==1) { if (seq[0]=='#') break; int n=strlen(seq); memset(d, 0, sizeof(d)); for (int i=n-1; i>=0; i--) for (int a=0; a<4; a++) for (int b=0; b<4; b++) if (a!=b) for (int s=0; s<3; s++) { d[i][a][b][s]=10*n; if (seq[i]=='.') { update(i,a,b,s,0,0); for (int t=0; t<4; t++) { update(i,a,b,s,1,t); update(i,a,b,s,2,t); } } else { update(i,a,b,s,1,pos[seq[i]]); update(i,a,b,s,2,pos[seq[i]]); } } int a=LEFT,b=RIGHT,s=0; for (int i=0; i<n; i++) { int f=action[i][a][b][s]/4; int t=action[i][a][b][s]%4; printf("%c",footch[f]); s=f; if (f==1) a=t; else if (f==2) b=t; } cout<<endl; } return 0;}1627
题意:
有n个人,把他们分成非空的两组,使得每个人都被分到一组,且同组中的人互相认识。要求两组的成员人数尽量接近。多解时输出任意方案,无解时输出No Solution。
分析:
自己没想到什么方法,紫书说要点是0-1背包。即对每个人的情况进行处理,假设a在组0,那么与a不是相互认识关系的人必须在组1,同理,与a不是相互认识的关系的人群为b,则与b不是相互关系的就必须在0。
按此情况判断是否合理,若合理,则存在解决方案。
通过dp对组1和组0之间的差值进行判断,对可能出现的差值进行标记。最后从小到大找寻最小差值即可,通过栈记录如何分组,最后输出。代码细节很多,很值得学习。
#include <algorithm>#include <iostream>#include <sstream>#include <cstring>#include <cstdlib>#include <string>#include <vector>#include <cstdio>#include <cmath>#include <queue>#include <stack>#include <map>#include <set>using namespace std;#define INF 0x3f3f3f3fconst int N=100005;const int mod=1e9+7;int n,g[105][105],color[105],diff[105],cc;vector<int> team[105][2];bool dfs(int u,int c) { color[u]=c; team[cc][c-1].push_back(u); for (int v=0; v<n; v++) { if (u!=v&&!(g[u][v]&&g[v][u])) { if (color[v]>0&&color[v]==color[u]) return false; if (!color[v]&&!dfs(v,3-c)) return false; } } return true;}bool build_graph() { memset(color, 0, sizeof(color)); cc=0; for (int i=0; i<n; i++) { if (!color[i]) { team[cc][0].clear(); team[cc][1].clear(); if (!dfs(i, 1)) return false; diff[cc]=team[cc][0].size()-team[cc][1].size(); cc++; } } return true;}int d[105][2*105],teamno[105];void print(int ans) { vector<int> team1,team2; for (int i=cc-1; i>=0; i--) { int t; if (d[i][ans-diff[i]+n]) { t=0; ans-=diff[i]; } else { t=1; ans+=diff[i]; } for (int j=0; j<team[i][t].size(); j++) { team1.push_back(team[i][t][j]); } for (int j=0; j<team[i][1^t].size(); j++) { team2.push_back(team[i][1^t][j]); } } printf("%d",team1.size()); for (int i=0; i<team1.size(); i++) { printf(" %d",team1[i]+1); } cout<<endl; printf("%d",team2.size()); for (int i=0; i<team2.size(); i++) { printf(" %d",team2[i]+1); } cout<<endl;}void dp() { memset(d, 0, sizeof(d)); d[0][0+n]=1; for (int i=0; i<cc; i++) { for (int j=-n; j<=n; j++) { if (d[i][j+n]) { d[i+1][j+diff[i]+n]=1; d[i+1][j-diff[i]+n]=1; } } } for (int ans=0; ans<=n; ans++) { if (d[cc][ans+n]) { print(ans); return; } if (d[cc][-ans+n]) { print(-ans); return; } }}int main() { int t,temp; cin>>t; while (t--) { cin>>n; memset(g, 0, sizeof(g)); for (int i=0; i<n; i++) { while (1) { scanf("%d",&temp); if (temp==0) break; g[i][temp-1]=1; } } if (n==1||!build_graph()) { cout<<"No solution\n"; } else dp(); if (t) { cout<<endl; } } return 0;}
0 0
- UVa-10618 Tango Tango Insurrection&& UVa-1627 Team them up!
- Tango Tango Insurrection UVA
- uva 10618 Tango Tango Insurrection (DP)WA
- UVA 10618 Tango Tango Insurrection(DP)
- uva 10618 Tango Tango Insurrection 动态规划
- uva 10618 Tango Tango Insurrection 解题报告
- UVa #10618 Tango Tango Insurrection (例题9-18)
- 【暑假】[深入动态规划]UVa 10618 Tango Tango Insurrection
- 10618 - Tango Tango Insurrection
- 100道动态规划——15 UVA 10618 Tango Tango Insurrection 复杂的转移方程。。
- Uva-1627-Team them up!
- UVA 1627 Team them up!
- Team them up! UVA
- Team them up! UVA
- Team them up! UVA
- poj1726 Tango Tango Insurrection
- UVa10618 Tango Tango Insurrection
- uva 1627 Team them up! 团队分组
- 红黑树的插入与删除
- java堆内存的划分
- 内存字节对齐
- HDU-1711-kmp模板
- ImageButton和ImageView的使用
- UVa-10618 Tango Tango Insurrection&& UVa-1627 Team them up!
- CodeForces 651B Beautiful Paintings
- 山东省第一届ACM大学生程序设计竞赛(原题) Ivan comes again!
- gtk 开发实践第三篇
- 用递归逆序一个单链表
- Hive分析窗口函数之CUME_DIST和PERCENT_RANK
- 时光商店下载网页设计
- 总结:如何驱动DS18B20温度传感器
- 前端插件