hdu3315My Brute KM算法
2015-08-07 14:53
232 查看
//starvae和xingxing各有n个小弟,每个小弟都有hp和攻击力 //对于第i个小弟,starvae小弟的攻击力为a[i] ,xingxing小弟的攻击力为b[i] //每场比赛,starvae小弟先攻击,然后一人攻击一次,谁的血量不先大于0谁输 //starvae用第i个小弟赢了比赛得到v[i]的分数,输了减去v[i]的分数 //刚开始是starvae的第i个小弟岁星星的第i个小弟 //问在原先的比赛顺序改变最少的前提下得到的最多分数 //如果没有在原有顺序改变最少这个前提,就是一个完备图的最大权匹配 //对于顺序改变最少,由于v[i] < 1000可以将原来的边都乘以1000,然后将原先对应的边w[i][i]的权值加1 //那么最终得到的答案在除以1000就行,而且在结果相同的情况下KM必然优先选择的是原先得边 #include<cstdio> #include<cstring> #include<iostream> using namespace std ; const int maxn = 110 ; const int inf = 0x3f3f3f3f ; int v[maxn] ; int w[maxn][maxn] ;int n ; int a[maxn] , s[maxn] , p[maxn] , b[maxn] ; int lx[maxn] , ly[maxn] , match[maxn] ; int visx[maxn] , visy[maxn] ,slack[maxn]; bool find(int x) { visx[x] = 1 ; for(int i = 1;i <= n;i++) { if(visy[i])continue ; int tmp = lx[x] + ly[i] - w[x][i] ; if(tmp ==0) { visy[i] = 1 ; if(match[i] == -1 || find(match[i])) { match[i] = x ; return true ; } } else slack[i] = min(slack[i] , tmp) ; } return false ; } int KM() { memset(match , -1 , sizeof(match)) ; memset(ly , 0 , sizeof(ly)) ; for(int i = 1;i <= n;i++) { lx[i] = -inf ; for(int j = 1;j <= n;j++) lx[i] = max(lx[i] , w[i][j]) ; } for(int i = 1;i <= n;i++) { for(int j = 1;j <= n;j++) slack[j] = inf ; while(1) { memset(visx , 0 ,sizeof(visx)) ; memset(visy , 0 , sizeof(visy)) ; if(find(i))break ; int d = inf ; for(int j = 1;j <= n;j++) if(!visy[j]) d = min(d , slack[j]) ; for(int j = 1;j <= n;j++) if(visx[j]) lx[j] -= d ; for(int j = 1;j <= n;j++) if(visy[j]) ly[j] += d ; else slack[j] -= d ; } } int ans = 0 ; for(int i = 1;i <= n;i++) ans += w[match[i]][i] ; return ans ; } int main() { //freopen("in.txt" ,"r" , stdin) ; while(scanf("%d" , &n) && n) { for(int i = 1;i <= n;i++) scanf("%d" , &v[i]) ; for(int i = 1;i <= n;i++) scanf("%d" ,&s[i]) ; for(int i = 1;i <= n;i++) scanf("%d" , &p[i]) ; for(int i = 1;i <= n;i++) scanf("%d" , &a[i]) ; for(int i = 1;i <= n;i++) scanf("%d" , &b[i]) ; for(int i = 1;i <= n;i++) { for(int j = 1;j <= n;j++) if((p[j] + a[i] - 1)/a[i] <= (s[i] + b[j] -1)/b[j]) w[i][j] = v[i]*1000 ; else w[i][j] = -v[i]*1000 ; w[i][i] += 1; } int ans = KM() ; if(ans/1000 <= 0) puts("Oh, I lose my dear seaco!") ; else { printf("%d " , ans/1000) ; printf("%.3lf" , (double)(ans%1000)/(double)n*100.0) ; puts("%") ; } } return 0 ; }
相关文章推荐
- hdu3722Card Game KM算法
- 日常问题记录--nested exception is java.lang.NoClassDefFoundError: org/apache/oro/text/regex/MalformedPatternExcept
- Android Paint的属性
- zabbix中文乱码解决
- 汇编---call & ret
- Js获取当前日期时间及其它操作
- Oralce INTERVAL
- 学习ExtJS Window常用方法
- ROS的软件包、节点
- SQL公用方法-根据拆封成表,并返回表结果
- 【MSSQL教程】#001 整体思维导图
- C++的模板特化 和 STL中iterator_traits模板的偏特化
- 多线程篇----NSoperation
- linux time 命令详解
- ip
- Spark开发指南
- Java学习之eclipse
- Mysql校验规则
- IOS数码测色计
- 各种测试视频序列