zoukankan      html  css  js  c++  java
  • poker P3793

    Description

    小F和小Z正在玩扑克牌。他们的扑克牌非常奇怪,正反两面都印有数字,分别是a[i],b[i]。一开始,桌面上摆着n张扑克牌。这个游戏一共进行n-1轮,每一轮他们可以选择两张扑克牌i,j,然后从中丢弃一张,剩下的一张放回桌面上。那么这一轮中他们的得分为min(a[i]b[j],a[j]b[i]).其中^表示异或。现在,小 F和小Z想知道这个游戏最少能拿多少分呢?


    Input

    每个测试点包含多组数据。输入数据的第一行为C,为数据个数。每组数据的第一行为n;接下来一行n个正整数表示每张牌正面的数字,接下来一行n个正整数表示每张牌反面的数字。


    Output

    每组数据输出一行,为这个游戏的最小得分。


    Hint

    样例解释:对于第二组数据,消除方案是,第一次选择第一张和第二张牌,扔掉第二张,得分为 3,第二次选择剩下的两张牌,得分为 2。


    数据规模与约定:对于20%的数据,n<=10。对于40%的数据,n<=20对于 70%的数据,n<=100对于100%的数据,有1<=n<=3000,一个测试点中所有n的和<=10^4.


    Solution

    这道题乍一看觉得是kruskal但是如果仔细看一下Hint就会发现其实用kruskal会 超 时(kruskal的时间复杂度是(m*logm,对于稀疏图适用)。And对于这道题,他是个稠密图,所以适用prim计算最小生成树(prim的时间复杂度是n^2),所以就没了。


    注意事项:
    1.只需要memset(vis,false,sizeof(vis));因为其他的变量已经在init()或者prim()的过程中更新了。
    2.只有一条看起来不好看。

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #define maxn 3005
    #define inf 0x3f3f3f3f
    using namespace std;
    struct data{
    	int leftt;
    	int rightt;
    }cardd[maxn];
    int g[maxn][maxn],minn[maxn],minp,minw;
    bool vis[maxn];
    int n,T;
    long long sumv;
    void Clear(){
    	//memset(g,inf,sizeof(g));
    	memset(vis,false,sizeof(vis));
    	//memset(minn,inf,sizeof(minn));
    	minp=minw=sumv=n=0;
    	//memset(cardd,0,sizeof(cardd));
    }
    void init(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&cardd[i].leftt);
    	}
    	for(int i=1;i<=n;i++){
    		scanf("%d",&cardd[i].rightt);
    	}
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=n;j++){
    			g[i][j]=min(cardd[i].leftt^cardd[j].rightt,cardd[i].rightt^cardd[j].leftt);
    		}
    	}
    }
    void prim(){
    	for(int i=1;i<=n;i++){
    		minn[i]=g[1][i];
    	}
    	vis[1]=true;
    	minn[1]=0;
    	for(int i=1;i<n;i++){
    		minw=inf;
    		for(int j=1;j<=n;j++){
    			if(minw>minn[j]&&!vis[j]){
    				minp=j;
    				minw=minn[j];
    			}
    		}
    		vis[minp]=true;
    		sumv+=minw;
    		for(int j=1;j<=n;j++){
    			minn[j]=min(minn[j],g[minp][j]);
    		}
    	}
    }
    int main(){
    	scanf("%d",&T);
    	for(int i=1;i<=T;i++){
    		Clear();
    		init();
    		prim();
    		printf("%lld
    ",sumv);
    	}
    	return 0;
    }
    
  • 相关阅读:
    oracle impdp 导入
    oracle权限的分配
    Oracle CASE WHEN 用法介绍
    Oracle自动执行任务(存储过程)
    PL/SQL注册码
    ORACLE基本的sql语句
    ORACLE导出导入问题和表空间问题
    PLSQL笔记
    JSEL 表达式
    asp.net HTTP教程一(HTTP运行期与页面执行模型 )
  • 原文地址:https://www.cnblogs.com/virtual-north-Illya/p/10045386.html
Copyright © 2011-2022 走看看