• UOJ#454-[UER #8]打雪仗【通信题】


    正题

    题目链接:https://uoj.ac/problem/454


    题目大意

    (Alice)有一个长度为(2n)(01)串,(Bob)(n)个在([1,2n])位置的下标表示它想要得到(01)串中这些位置的值,现在两个人可以向对方传输不超过(m)(0/1)字符,要求使得(Bob)可以得到答案。

    (1leq nleq 1000,m=1350)


    解题思路

    两种方法,都是平均两边的传输信息。
    第一种方法是从左到右传输(01)串,由(Bob)考虑若一个位置需要传输,那么传输(1),然后(Alice)传输这个位置给他并考虑下一个位置。否则传输(0),然后(Alice)跳过这个位置传输下一个位置给她然后再考虑下一个位置。
    不难发现这样对于(01)隔开的情况可以省略很多次数,所以我们直接随机打乱整个序列然后这样做即可。

    第二种方法是将序列分为三块,(Bob)用二进制告诉(Alice)需要信息最多的那个块。然后剩下两个块由(Bob)告诉(Alice)需要传输哪些位置。
    这样的次数(Alice)严格小于(frac{2}{3}n imes 2)(Bob)严格小于(frac{4}{3}n+2),都在(1350)次内。

    因为第二种方法比较普遍所以代码使用的是第一种方法


    code

    Alice

    #include <iostream>
    #include <fstream>
    #include <string>
    #include<cstdlib>
    #include<cstdio>
    #include<algorithm>
    
    using namespace std;
    
    ifstream fin;
    char get_bit() {
    	return getchar();
    }
    void send_bit(char ch) {
    	putchar(ch);
    	fflush(stdout);
    }
    
    int n, m,c[2100],r[2100];
    string s;
    void init_t() {
    	fin.open("alice.in");
    	fin >> n >> m >> s;
    }
    int Z=17;
    int randd(){
    	Z++;
    	return (Z*1931ll+Z*Z*3ll)%32767;
    }
    int main()
    {
    	init_t();
    	for(int i=1;i<=2*n;i++)r[i]=i;
    	for(int i=1;i<=20*n;i++)swap(r[randd()%(2*n)+1],r[randd()%(2*n)+1]);
    	for(int i=1;i<=2*n;i++)c[r[i]]=s[i-1];
    	int i=1;
    //	for(int i=1;i<=2*n;i++)send_bit(c[i]); 
    	while(i<=2*n){
    		char z=get_bit();
    		if(z==EOF)break;
    		if(z=='1'){send_bit(c[i]);i++;}
    		else{i++;if(i>2*n)break;send_bit(c[i]);i++;}
    	}
    	return 0;
    }
    

    Bob

    #include <iostream>
    #include <fstream>
    #include<cstdlib>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    ifstream fin;
    char get_bit() {
    	return getchar();
    }
    void send_bit(char ch) {
    	putchar(ch);
    	fflush(stdout);
    }
    
    const int N = 1000;
    
    int n, m, p[N + 1],r[N*2+10],w[N*2+10];
    char s[N+1];
    ofstream fout;
    void answer() {
    	fout.open("bob.out");
    	for(int i=1;i<=n;i++)
    		fout<<s[i];
    	fout<<endl; 
    	exit(0);
    }
    void init_t() {
    	int x;
    	fin.open("bob.in");
    	fin >> n >> m;
    	for (x = 1; x <= n; ++x) fin >> p[x];
    }
    int Z=17;
    int randd(){
    	Z++;
    	return (Z*1931ll+Z*Z*3ll)%32767;
    }
    int main() {
    	init_t();
    	for(int i=1;i<=2*n;i++)r[i]=i;
    	for(int i=1;i<=20*n;i++)swap(r[randd()%(2*n)+1],r[randd()%(2*n)+1]);
    	for(int i=1;i<=n;i++)p[i]=r[p[i]],w[p[i]]=i;
    	sort(p+1,p+1+n);
    	int z=1,i=1;
    	while(i<=n){
    		if(p[i]==z){send_bit('1');s[w[p[i]]]=get_bit();z++;i++;}
    		else{
    			send_bit('0');z++;
    			if(z>2*n)break;
    			s[w[p[i]]]=get_bit();
    			if(p[i]==z)i++;z++;
    		}
    	}
    	answer();
    	return 0;
    }
    
  • 相关阅读:
    CSS初识
    HTML 初识
    索引
    表查询前之数据导入
    mysql练习2
    AMP+EPP3.0的开发环境配置
    C++异步编程资料汇集贴
    Windows8中如何打包和安装一个本地的Metro类型应用(转)
    std::string, std::wstring, wchar_t*, Platform::String^ 之间的相互转换
    windows RT开发笔记:WinRT DLL及其调用研究
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15128098.html
Copyright © 2020-2023  润新知