约数倍数选卡片---博弈论

来源:互联网 发布:瓶中船的制作材料淘宝 编辑:程序博客网 时间:2024/04/30 08:10

超时,得分60,满分100
问题描述
  闲暇时,福尔摩斯和华生玩一个游戏:
  在N张卡片上写有N个整数。两人轮流拿走一张卡片。要求下一个人拿的数字一定是前一个人拿的数字的约数或倍数。例如,某次福尔摩斯拿走的卡片上写着数字“6”,则接下来华生可以拿的数字包括:
  1,2,3, 6,12,18,24 ….
  当轮到某一方拿卡片时,没有满足要求的卡片可选,则该方为输方。
  请你利用计算机的优势计算一下,在已知所有卡片上的数字和可选哪些数字的条件下,怎样选择才能保证必胜!
  当选多个数字都可以必胜时,输出其中最小的数字。如果无论如何都会输,则输出-1。
输入格式
  输入数据为2行。第一行是若干空格分开的整数(每个整数介于1~100间),表示当前剩余的所有卡片。
  第二行也是若干空格分开的整数,表示可以选的数字。当然,第二行的数字必须完全包含在第一行的数字中。
输出格式
  程序则输出必胜的招法!!
样例输入
2 3 6
3 6
样例输出
3
样例输入
1 2 2 3 3 4 5
3 4 5
样例输出
4

#include "iostream"#include "algorithm"#include "vector"#include "set"#include "string.h"#include "stdio.h"using namespace std;vector<int> choose;  //被选择的数vector<int> table[101];  //table[i]中存放choose[i]的约数或倍数int n;int num[101];  //num[i]为i出现的次数vector<int> a;int dfs(int choice){    for(int i=0; i<table[choice].size(); i++)    {        int newChoice = table[choice][i];        if(num[newChoice])        {            num[newChoice]--;            int tmp = dfs(newChoice);            num[newChoice]++;            if(tmp == -1)                return 1;        }    }    return -1;}int main(){    memset(num, 0, sizeof(num));    int i = 0;    char c;    int b;    while(1)    {        scanf("%d", &b);        a.push_back(b);        num[a[i]]++;        c = getchar();        if(c == '\n')            break;        i++;    }    n = i;    int x;    while(1)    {        scanf("%d", &x);        choose.push_back(x);        c = getchar();        if(c == '\n')            break;    }    sort(choose.begin(), choose.end());    int m = choose.size();    for(i=0; i<a.size(); i++)    {        x = a[i];        for(int j=1; j<=100; j++)            if(num[j] && (x % j == 0 || j % x == 0))                table[x].push_back(j);    }    for(i=0; i<m; i++)    {        x = choose[i];        num[x]--;        int ans = dfs(x);        num[x]++;        if(ans == -1)        {            cout << x;            return 0;        }    }    cout << -1;    return 0;}
0 0
原创粉丝点击