您的位置:首页 > 运维架构

Topcoder SRM 144 Div1 550(数学和dp问题求方案数,很有意思)

2014-09-13 04:06 731 查看

Problem Statement

 In most states, gamblers can choose from a wide variety of different lottery games. The rules of a lottery are defined by two integers (choices and
blanks) and two boolean variables (sorted and unique).
choices represents the highest valid number that you may use on your lottery ticket. (All integers between 1 and
choices, inclusive, are valid and can appear on your ticket.) blanks represents the number of spots on your ticket where numbers can be written.

The sorted and unique variables indicate restrictions on the tickets you can create. If
sorted is set to true, then the numbers on your ticket must be written in non-descending order. If
sorted is set to false, then the numbers may be written in any order. Likewise, if
unique is set to true, then each number you write on your ticket must be distinct. If
unique is set to false, then repeats are allowed.

Here are some example lottery tickets, where choices = 15 and blanks = 4:

{3, 7, 12, 14} -- this ticket is unconditionally valid.
{13, 4, 1, 9} -- because the numbers are not in nondescending order, this ticket is valid only if
sorted = false.
{8, 8, 8, 15} -- because there are repeated numbers, this ticket is valid only if
unique = false.
{11, 6, 2, 6} -- this ticket is valid only if sorted = false and
unique = false.
Given a list of lotteries and their corresponding rules, return a list of lottery names sorted by how easy they are to win. The probability that you will win a lottery is equal to (1 / (number of valid lottery tickets for that game)). The easiest lottery
to win should appear at the front of the list. Ties should be broken alphabetically (see example 1).

Definition

 
Class:Lottery
Method:sortByOdds
Parameters:vector <string>
Returns:vector <string>
Method signature:vector <string> sortByOdds(vector <string> rules)
(be sure your method is public)

Limits

 
Time limit (s):2.000
Memory limit (MB):64

Constraints

-rules will contain between 0 and 50 elements, inclusive.
-Each element of rules will contain between 11 and 50 characters, inclusive.
-Each element of rules will be in the format "<NAME>:_<CHOICES>_<BLANKS>_<SORTED>_<UNIQUE>" (quotes for clarity). The underscore character represents exactly one space. The string will have no leading or trailing spaces.
-<NAME> will contain between 1 and 40 characters, inclusive, and will consist of only uppercase letters ('A'-'Z') and spaces (' '), with no leading or trailing spaces.
-<CHOICES> will be an integer between 10 and 100, inclusive, with no leading zeroes.
-<BLANKS> will be an integer between 1 and 8, inclusive, with no leading zeroes.
-<SORTED> will be either 'T' (true) or 'F' (false).
-<UNIQUE> will be either 'T' (true) or 'F' (false).
-No two elements in rules will have the same name.

Examples

0) 
 
{"PICK ANY TWO: 10 2 F F"
,"PICK TWO IN ORDER: 10 2 T F"
,"PICK TWO DIFFERENT: 10 2 F T"
,"PICK TWO LIMITED: 10 2 T T"}

Returns:
{ "PICK TWO LIMITED",
"PICK TWO IN ORDER",
"PICK TWO DIFFERENT",
"PICK ANY TWO" }

The "PICK ANY TWO" game lets either blank be a number from 1 to 10. Therefore, there are 10 * 10 = 100 possible tickets, and your odds of winning are 1/100.

The "PICK TWO IN ORDER" game means that the first number cannot be greater than the second number. This eliminates 45 possible tickets, leaving us with 55 valid ones. The odds of winning are 1/55.

The "PICK TWO DIFFERENT" game only disallows tickets where the first and second numbers are the same. There are 10 such tickets, leaving the odds of winning at 1/90.

Finally, the "PICK TWO LIMITED" game disallows an additional 10 tickets from the 45 disallowed in "PICK TWO IN ORDER". The odds of winning this game are 1/45.

1) 
 
{"INDIGO: 93 8 T F",
"ORANGE: 29 8 F T",
"VIOLET: 76 6 F F",
"BLUE: 100 8 T T",
"RED: 99 8 T T",
"GREEN: 78 6 F T",
"YELLOW: 75 6 F F"}

Returns: { "RED",  "ORANGE",  "YELLOW",  "GREEN",  "BLUE",  "INDIGO",  "VIOLET" }

Note that INDIGO and BLUE both have the exact same odds (1/186087894300). BLUE is listed first because it comes before INDIGO alphabetically.

2) 
 
{}

Returns: { }

Empty case

题目很有意思,分4种情况,2种直接数学计算,2种dp一下就好了

很喜欢tc的这种题目

//Hello. I'm Peter.
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double ld;
#define peter cout<<"i am peter"<<endl
#define input freopen("data.txt","r",stdin)
#define randin srand((unsigned int)time(NULL))
#define INT (0x3f3f3f3f)*2
#define LL (0x3f3f3f3f3f3f3f3f)*2
#define gsize(a) (int)a.size()
#define len(a) (int)strlen(a)
#define slen(s) (int)s.length()
#define pb(a) push_back(a)
#define clr(a) memset(a,0,sizeof(a))
#define clr_minus1(a) memset(a,-1,sizeof(a))
#define clr_INT(a) memset(a,INT,sizeof(a))
#define clr_true(a) memset(a,true,sizeof(a))
#define clr_false(a) memset(a,false,sizeof(a))
#define clr_queue(q) while(!q.empty()) q.pop()
#define clr_stack(s) while(!s.empty()) s.pop()
#define rep(i, a, b) for (int i = a; i < b; i++)
#define dep(i, a, b) for (int i = a; i > b; i--)
#define repin(i, a, b) for (int i = a; i <= b; i++)
#define depin(i, a, b) for (int i = a; i >= b; i--)
#define pi 3.1415926535898
#define eps 1e-6
#define MOD 1000000007
#define MAXN 100100
#define N
#define M 200
struct Games
{
string name;
int choice;
int blank;
bool sort;
bool unique;
ll ans;
}game[M+100];
bool comp(const Games a,const Games b)
{//按ans从小到大排序,就相当于按1/ans从大到小排序,当然string name也要排字典序
if(a.ans!=b.ans) return a.ans<b.ans;
else return a.name<b.name;
}
void check(int sz);
int pos_colon(string s)
{//找到':'的位置,输入时候用
int res=0;
int len=slen(s);
rep(i,0,len)
{
if(s[i]==':')
{
res=i;
break;
}
}

4000
return res;
}
int idx(char c){
return c-'0';
}
int changestringtoint(string s)
{//讲字符串数字转换成实际整数
int len=slen(s);
int res=0;
int ten=1;
depin(i,len-1,0)
{
res+=idx(s[i])*ten;
ten*=10;
}
return res;
}
ll A(int n,int m)
{//排列问题 A(n,m)
ll res=1,t=(ll)n;
repin(i,1,m)
{
res*=t;
t--;
}
return res;
}
ll powpow(int n,int m)
{//n的m次方
ll res=1,t=(ll)n;
repin(i,1,m)
{
res*=t;
}
return res;
}
ll dp[10][110];//dp[i][j]代表第i个位置放j这个数的时候方案数是多少
class Lottery
{
public:
vector <string> sortByOdds(vector <string> rules)
{
int sz=gsize(rules);
string s;
rep(i,0,sz)
{
s=rules[i];
int pos=pos_colon(s);
game[i].name.clear();
rep(j,0,pos)
{
game[i].name+=rules[i][j];
}
s.erase(0,pos+1);
//删除后用istringstream处理,非常方便
istringstream ss(s);
int t=0;
while(ss>>s)
{
t++;
if(t==1) game[i].choice=changestringtoint(s);
else if(t==2) game[i].blank=changestringtoint(s);
else if(t==3)
{
if(s[0]=='T') game[i].sort=true;
else game[i].sort=false;
}
else if(t==4)
{
if(s[0]=='T') game[i].unique=true;
else game[i].unique=false;
}
}
}
//分4种情况计算,2种直接计算,2种dp
int c,b;
bool sorted,unique;
rep(ii,0,sz)
{
c=game[ii].choice;
b=game[ii].blank;
sorted=game[ii].sort;
unique=game[ii].unique;
if(!sorted && !unique)
{//可不单调可重复 直接算 pow
game[ii].ans=powpow(c,b);
}
else if(!sorted && unique)
{//可不单调不重复 A(c,b)
game[ii].ans=A(c,b);
}
else if(sorted && !unique)
{//单调可重复 dp 来做
clr(dp);
repin(i,1,c)
{//初始化,代表第1个位置i这个数方案数,当然是1
dp[1][i]=1;
}
repin(i,2,b)
{
repin(j,1,c)
{//枚举每个位置的每个数
repin(k,1,j)
{//它的答案就是上一个位置所有<=它的数的方案数之和
dp[i][j]+=dp[i-1][k];
}
}
}
game[ii].ans=0;
repin(i,1,c)
{//结果就是最后一个位置所有数的方案数之和
game[ii].ans+=dp[b][i];
}
}
else if(sorted && unique)
{//单调不重复 也是 dp,就一个地方不一样
clr(dp);
repin(i,1,c)
{//初始化,代表第1个位置i这个数方案数,当然是1
dp[1][i]=1;
}
repin(i,2,b)
{
repin(j,1,c)
{//枚举每个位置的每个数
rep(k,1,j)
{//它的答案就是上一个位置所有<它的数的方案数之和
dp[i][j]+=dp[i-1][k];
}
}
}
game[ii].ans=0;
repin(i,1,c)
{//结果就是最后一个位置所有数的方案数之和
game[ii].ans+=dp[b][i];
}
}
}
//根据要求排个序
sort(game,game+sz,comp);
vector<string>res;
rep(i,0,sz)
{//构成vetor<string>res
res.pb(game[i].name);
}
return res;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: