本题地址: http://www.luogu.org/problem/show?pid=2614
第一行,两个整数n,T,表示谱子行数以及速度(拍每分)
接下来n行,给出乐谱。
一个整数,表示演奏需要花费的时间,单位秒,舍去小数部分。
# include
# include
# include
# include
# include
using namespace std;
const int MAXN = 10001;
int N,T;
int stacksize;
int pos = 0;
int k;
double MusicLen[MAXN];
double Ans;
string str;
void Init(){
k = 0;
stacksize = 0;
str.clear();
Ans = 0.0;
for (int i=1;i!=MAXN;++i) MusicLen[i] = 0.0;
MusicLen[0] = 1;
}
void Read(){
scanf("%d%d",&N,&T);
char c = getchar();
while (c != EOF){
if (c != ' ' && c != '\n') str.push_back(c);
c = getchar();
}
}
void Cut(){
int len = str.size();
for (int i=1;i!=len;++i){
switch(str[i]){
case '-':
++k;
break;
case '.':
MusicLen[pos] *= 1.5;
break;
case '(':
++stacksize;
break;
case ')':
--stacksize;
break;
default:
if (k != 0) MusicLen[pos] *= k+1;
k = 0;
++pos;
MusicLen[pos] = pow(0.5,stacksize);
}
}
}
void Sum(){
for (int i=0;i<=pos;++i){
// printf("%f\n",MusicLen[i]);
Ans += MusicLen[i];
}
}
int main(){
Init();
Read();
Cut();
if (k != 0) MusicLen[pos] *= k+1;
Sum();
// printf("%f\n",Ans);
cout << floor(Ans * 60.0 / (double)T) << endl;
return 0;
}
本题地址: http://www.luogu.org/problem/show?pid=2622
前两行两个数,n m
接下来m行,每行n个数,a[i][j]表示第i个开关对第j个灯的效果。
一个整数,表示最少按按钮次数。如果没有任何办法使其全部关闭,输出-1
# include
using namespace std;
const int MAXSTATE = 2048;
const int MAXM = 101;
const int MAXN = 11;
const int MAXQ = 5001; /*Faster And Safer : Round Queue*/
const int INF = 10000000; /*Infinite*/
int Q[MAXQ];
int head,tail;
int Qhead,Qtail;
int NowState;
int NewState;
int LightWay[MAXSTATE];
int Way[MAXM][MAXN];
/*N - Light(Point) Number, M - Oper(Way) Number*/
int N,M;
int StateSize;
int main(){
scanf("%d%d",&N,&M);
for (int i=0;i!=M;++i){
for (int j=0;j!=N;++j){
scanf("%d",&Way[i][j]);
}
}
/*Init: All Point Expect Begining's Way is INF*/
StateSize = (1 << N);
for (int i=0;i!=StateSize;++i){
LightWay[i] = INF;
}
LightWay[StateSize - 1] = 0;
/*Init Queue*/
Qhead = Qtail = head = tail = 0;
Q[Qtail] = StateSize - 1;
/*!!!Begin SPFA!!!*/
while (head >= tail){
NowState = Q[Qtail];
for (int i=0;i!=M;++i){
/*To Every Opers*/
NewState = NowState;
for (int j=0;j!=N;++j){
if (Way[i][j] == -1){
NewState = (NewState | (1<
else if (Way[i][j] == 1){
NewState = (NewState & (~(1<
}
if (LightWay[NewState] > LightWay[NowState] + 1){
LightWay[NewState] = LightWay[NowState] + 1;
++Qhead;
++head;
if (Qhead == MAXQ) Qhead = 0;
Q[Qhead] = NewState;
}
}
++Qtail;
++tail;
if (Qtail == MAXQ) Qtail = 0;
}
if (LightWay[0] == INF){
printf("-1\n");
}
else{
printf("%d\n",LightWay[0]);
}
return 0;
}
本题地址: http://www.luogu.org/problem/show?pid=2633
第一行是城市的数量n(1<=n<=16000)。第二行包含n个整数,依次表示每座城市的收益,每个数是-1000到1000之间的整数。下面的n-1行描述了道路:每行包含2个整数a和b,用一个空格隔开,表示这两个城市之间有一条道路。
输出格式:仅有一个数,表示最大收益。
# include
# include
using namespace std;
const int INF = 10000000;
const int MAXN = 16001;
const int MAXBOOL = 2;
int f[MAXN][MAXBOOL];
int w[MAXN];
int N;
int a,b;
bool isLink[MAXN][MAXN];
bool find[MAXN];
bool use[MAXN];
bool isLeaf;
inline int max(int a,int b){
return a > b ? a : b;
}
/*记忆化搜索*/
void dfs(int pos){
find[pos] = true;
isLeaf = true;
f[pos][0] = -INF;
f[pos][1] = 0;
for (int i=0;i!=N;++i){
if (isLink[pos][i]){
if (use[i]) continue;
if (!find[i]) dfs(i);
isLeaf = false;
if (f[i][1] > 0){
f[pos][1] += f[i][1];
}
if (max(f[i][0],f[i][1]) > f[pos][0]){
f[pos][0] = max(f[i][0],f[i][1]);
}
use[i] = true;
}
}
if (isLeaf){
f[pos][0] = 0;
f[pos][1] = w[pos];
return;
}
else{
f[pos][1] += w[pos];
}
return;
}
int main() {
memset(isLink,false,sizeof(isLink));
memset(find,false,sizeof(find));
memset(use,false,sizeof(use));
scanf("%d",&N);
for (int i=0;i!=N;++i){
scanf("%d",&w[i]);
}
for (int i=1;i!=N;++i){
scanf("%d%d",&a,&b);
isLink[a-1][b-1] = isLink[b-1][a-1] = true;
}
use[0] = true;
dfs(0);
printf("%d\n",max(f[0][0],f[0][1]));
return 0;
}