三家人
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 2170 Solved: 838
[ Submit][ Status][ Web Board]
Description
Input
输入第一行为数据组数T (T<=20)。每组数据仅一行,包含三个整数x, y, z (1<=x, y<=10,1<=z<=1000)。
Output
对于每组数据,输出一个整数,即A 太太应得的金额(单位:元)。
Sample Input
2
5 4 90
8 4 123
Sample Output
60
123
HINT
如果使用浮点数,请小心误差,输出时尽量用四舍五入。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
int main()
{
double n,m,z;
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lf %lf %lf",&n,&m,&z);
double sum=n+m;
sum/=3;
double ans=n-sum+m-sum;
double ans1=z*(n-sum)/ans;
printf("%.0lf\n",ans1);
}
return 0;
}
机器人的指令
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 1790 Solved: 651
[ Submit][ Status][ Web Board]
Description
数轴原点有一个机器人。该机器人将执行一系列指令,你的任务是预测所有指令执行完毕之后它的位置。
·LEFT:往左移动一个单位
·RIGHT: 往右移动一个单位
·SAME AS i: 和第i 条执行相同的动作。输入保证i 是一个正整数,且不超过之前执行指令数
Input
输入第一行为数据组数T (T<=100)。每组数据第一行为整数n (1<=n<=100),即指令条数。以下每行一条指令。指令按照输入顺序编号为1~n。
Output
对于每组数据,输出机器人的最终位置。每处理完一组数据,机器人应复位到数轴原点。
Sample Input
2
3
LEFT
RIGHT
SAME AS 2
5
LEFT
SAME AS 1
SAME AS 2
SAME AS 1
SAME AS 4
Sample Output
1
-5
思路:用一个数组记录每一次做了哪个操作,-1表示向左,1表示向右即可
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
int a[150];
int main()
{
char op[10];
int T,n,t;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
int now=0;
for(int i=1;i<=n;i++)
{
scanf("%s",op);
if(strcmp(op,"LEFT")==0)
{
now--;
a[i]=-1;
}
else if(strcmp(op,"RIGHT")==0)
{
now++;
a[i]=1;
}
else
{
scanf("%s",op);
scanf("%d",&t);
a[i]=a[t];
now+=a[i];
}
}
printf("%d\n",now);
}
return 0;
}
Updating a Dictionary
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 745 Solved: 180
[ Submit][ Status][ Web Board]
Description
Input
Output
Sample Input
3
{a:3,b:4,c:10,f:6}
{a:3,c:5,d:10,ee:4}
{x:1,xyz:123456789123456789123456789}
{xyz:123456789123456789123456789,x:1}
{first:1,second:2,third:3}
{third:3,second:2}
Sample Output
+d,ee
-b,f
*c
No changes
-first
思路:用两个map去存下两个字符串里边的信息,然后作比较即可
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <algorithm>
using namespace std;
map<string,string> Map1,Map2;
char str[2][105];
string keys1[100],keys2[100],value1[100],value2[100];
string add[100],del[100],change[100];
int cnt1,cnt2;
int num_add,num_del,num_change;
bool cmp(string a,string b)
{
if(a.compare(b) < 0) return true;
return false;
}
int main()
{
int t,cas = 1;
scanf("%d",&t);
while(t--)
{
bool nochange = true;
num_add = num_del = num_change = 0;
cnt1 = cnt2 = 0;
int len1,len2;
Map1.clear();
Map2.clear();
cin >> str[0];
len1 = strlen(str[0]);
for(int i = 0; i < len1; i++)
{
if(str[0][i] == '{') continue;
if(str[0][i] == '}') continue;
int j = i;
keys1[++cnt1] = "";
value1[cnt1] = "";
bool flag = true;
while(j < len1 - 1 && str[0][j] != ',')
{
if(str[0][j] == ':')
{
j++;
flag = false;
continue;
}
if(flag)
keys1[cnt1] += str[0][j];
else value1[cnt1] += str[0][j];
j++;
}
i = j;
Map1[keys1[cnt1]] = value1[cnt1];
}
cin >> str[1];
len2 = strlen(str[1]);
for(int i = 0; i < len2 ; i++)
{
if(str[1][i] == '{') continue;
if(str[1][i] == '}') continue;
int j = i;
keys2[++cnt2] = "";
value2[cnt2] = "";
bool flag = true;
while(j < len2 - 1 && str[1][j] != ',')
{
if(str[1][j] == ':')
{
j++;
flag = false;
continue;
}
if(flag)
keys2[cnt2] += str[1][j];
else value2[cnt2] += str[1][j];
j++;
}
i = j;
Map2[keys2[cnt2]] = value2[cnt2];
}
for(int i = 1; i <= cnt2; i++) //找新的keys
{
if(Map1.find(keys2[i]) == Map1.end())
{
add[++num_add] = keys2[i];
nochange = false;
}
}
for(int i = 1; i <= cnt1; i++) //找删除的keys
{
if(Map2.find(keys1[i]) == Map2.end())
{
del[++num_del] = keys1[i];
nochange = false;
}
}
for(int i = 1; i <= cnt1; i++)
{
if(Map2.find(keys1[i]) != Map2.end())
{
string tmp = Map2[keys1[i]];
// cout << tmp << " " << value1[i] << endl;
if(tmp.compare(value1[i]) != 0)
{
change[++num_change] = keys1[i];
nochange = false;
}
}
}
if(cas > 1) printf("\n");
cas++;
if(nochange == true)
{
printf("No changes\n");
continue;
}
sort(add+1,add+1+num_add,cmp);
sort(del+1,del+1+num_del,cmp);
sort(change+1,change+1+num_change,cmp);
if(num_add != 0) printf("+");
for(int i = 1; i < num_add; i++)
{
cout << add[i] << ",";
}
if(num_add != 0)
cout << add[num_add] << endl;
if(num_del != 0) printf("-");
for(int i = 1; i < num_del; i++)
{
cout << del[i] << ",";
}
if(num_del != 0)
cout << del[num_del] << endl;
if(num_change != 0) printf("*");
for(int i = 1; i < num_change; i++)
{
cout << change[i] << ",";
}
if(num_change != 0)
cout << change[num_change] << endl;
}
return 0;
}
平方根大搜索
Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 184 Solved: 98
[ Submit][ Status][ Web Board]
Description
Input
输入第一行为数据组数T (T<=20)。以下每行为一组数据,仅包含一个整数n (2<=n<=1,000,000)和一个长度不超过20的非空01串S。
Output
对于每组数据,输出S的第一次出现中,第一个字符的位置。小数点后的第一个数字的位置为0。输入保证答案不超过100。
Sample Input
2
2 101
1202 110011
Sample Output
2
58
思路:此题可以用手动模拟开方做,不过实在太麻烦了,并且如果事先不知道模拟的过程是做不出来的。
所以这里我们用二分去找开方即可,然后手动转换为二进制,最后暴力比较。
代码:
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.Format;
import java.util.Scanner;
public class Main {
final static BigDecimal eps = BigDecimal.valueOf(0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001);
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int tcase = sc.nextInt();
while(tcase-- > 0){
String str = sc.next();
String str1 = sc.next();
BigDecimal a = new BigDecimal(str);
a.setScale(200);
BigDecimal l = BigDecimal.ZERO;
l.setScale(200);
BigDecimal r = a;
r.setScale(200);
BigDecimal mid = new BigDecimal("0");
mid.setScale(200);
while(l.add(eps).compareTo(r)<=0){
mid = l.add(r).divide(BigDecimal.valueOf(2));
if(mid.multiply(mid).compareTo(a)>0){
r = mid;
}else{
l = mid;
}
}
String s = mid.toString();
int idx = 0;
for(int i=0;i<s.length();i++){
if(s.charAt(i)=='.'){
idx = i;
break;
}
}
s = s.substring(idx+1, s.length());
s = "0."+s;
mid = new BigDecimal(s);
String ans = "";
for(int i=1;i<=200;i++){
mid = mid.multiply(BigDecimal.valueOf(2));
if(mid.compareTo(BigDecimal.ONE)>=0){
ans+=1;
mid = mid.subtract(BigDecimal.ONE);
}else{
ans+=0;
}
}
int res = ans.indexOf(str1);
System.out.println(res);
}
}
}
最短的名字
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1126 Solved: 422
[ Submit][ Status][ Web Board]
Description
Input
Output
对于每组数据,输出所有人名字的字母总数。
Sample Input
1
3
aaaaa
bbb
abababab
Sample Output
5
思路:用字典树存下所有的串,在子点数上记录每一个位置被经过了多少次。然后从根结点开始扫,每次扫到1就ans+=len,然后return即可
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
#define N 1000005
char a[N];
typedef struct Tree
{
struct Tree *next[26];
int v;
};
Tree *root;
int ans;
void inits(char *op)
{
Tree *q=root,*p;
for(int i=0; i<strlen(op); i++)
{
int j=op[i]-'a';
if(q->next[j]==NULL)
{
p=new Tree;
for(int k=0; k<26; k++)
p->next[k]=NULL;
p->v=0;
q->next[j]=p;
}
q->v++;
q=q->next[j];
}
q->v++;
}
void finds(Tree *q,int num)
{
if(q->v==1)
{
ans+=num;
return;
}
for(int i=0; i<26; i++)
{
if(q->next[i]==NULL) continue;
finds(q->next[i],num+1);
}
}
void clears(Tree *q)
{
for(int i=0; i<26; i++)
if(q->next[i]!=NULL)
clears(q->next[i]);
free(q);
}
int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
root=new Tree;
for(int i=0; i<26; i++)
root->next[i]=NULL;
root->v=0;
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
scanf("%s",a);
inits(a);
}
ans=0;
finds(root,0);
printf("%d\n",ans);
clears(root);
}
return 0;
}
Kingdoms
Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 427 Solved: 137
[ Submit][ Status][ Web Board]
Description
Input
Output
For each test case, print the maximal accessible population.
Sample Input
2
4 6 6
500 400 300 200
1 2 4
1 3 3
1 4 2
4 3 5
2 4 6
3 2 7
4 6 5
500 400 300 200
1 2 4
1 3 3
1 4 2
4 3 5
2 4 6
3 2 7
Sample Output
1100
1000
题意:有n个城市和m条路,k块钱,每个城市有一个权值。国王居住在1号城市,现在问你如何选出一些边总费用不超过k,使得跟1号城市连接的所有城市权值最大
思路:数据量比较小,城市只有16个,所有我们可以用状态保存下16个城市所有的状态,1表示已经选入,0表示未选入。
这样状态总数也只有1<<16=65536 所以我们可以枚举所有的状态,然后用prim求出连通这些为1的结点所需要的最小费用是否大于k,枚举完后在费用<=k的状态里面取权值最大的即可。 注意1号城市一定会选入,这样状态可以少一维。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <algorithm>
using namespace std;
const int INF = 999999999;
const int N = 20;
int weight[N];
int graph[N][N];
int n,m,cost;
int a[N];
void init(int n)
{
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
graph[i][j] = INF;
if(i==j) graph[i][j] = 0;
}
}
}
bool vis[N];
int low[N];
int prim(int n,int pos)
{
memset(vis,0,sizeof(vis));
for(int i=0; i<n; i++)
{
low[a[i]] = graph[pos][a[i]];
}
vis[pos] = true;
int k = 0;
for(int i=1; i<n; i++)
{
int Min = INF;
for(int j=0; j<n; j++)
{
if(!vis[a[j]]&&low[a[j]]<Min)
{
pos = a[j];
Min = low[a[j]];
}
}
vis[pos] = true;
k +=Min;
if(k>cost) return -1;
for(int j=0; j<n; j++)
{
if(!vis[a[j]]&&low[a[j]]>graph[pos][a[j]]) low[a[j]] = graph[pos][a[j]];
}
}
return k;
}
int main()
{
int tcase,u,v,w;
scanf("%d",&tcase);
while(tcase--)
{
scanf("%d%d%d",&n,&m,&cost);
init(n);
for(int i=1; i<=n; i++)
{
scanf("%d",&weight[i]);
}
for(int i=1; i<=m; i++)
{
scanf("%d%d%d",&u,&v,&w);
graph[u][v] = graph[v][u] = min(graph[v][u],w);
}
int MAX = -1,state = 1<<n,pos,COST = -1,temp;
for(int i=state - 1; i > 0; i--)
{
if(!(i&1)) continue;
pos = 0;
temp = 0;
for(int j=0; j<n; j++)
{
if((i>>j)&1)
{
a[pos++] = j+1;
temp+=weight[j+1];
}
}
int cost = prim(pos,a[0]);
if(cost!=-1)
{
COST = max(COST,temp);
if(i == state - 1) break;
}
}
printf("%d\n",COST);
}
return 0;
}
Collecting Coins
Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 315 Solved: 68
[ Submit][ Status][ Web Board]
Description
Input
Output
For each test case, print the maximal number of coins you can collect.
Sample Input
3
3 4
S.OC
..O.
.XCX
4 6
S.X.CC
..XOCC
...O.C
....XC
4 4
.SXC
OO.C
..XX
.CCC
Sample Output
1
6
3
题意:有一个n*m的矩阵,S是人开始的位置,O是石头,C是金币,X是墙。石头最多只能推一次,现在问你最多能拿到多少个金币
思路:我们不能直接用人去做BFS一条路走到死。肯定会TLE,因为在碰到石头之前的状态其实都是一样的,而你用BFS会多出很多很多状态。
所以我们先用BFS跑出石头没动时人能走到的所有的位置,并且把吃到的金币数记下来,对应的图从C改成.
然后用DFS去枚举石头移动的所有情况(向四个方向移动),最后在所有情况里面取吃到的金币数最大的那个就可以了。注意要开三维数组保存上一层的图和标记数组。
代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
int n,m,ans,last_ans;
char ma[6][11][11];
int dir[4][2]= {-1,0,1,0,0,-1,0,1};
struct Node
{
int x,y;
} stone[5];
int cnt;
int vis[6][15][15];
int flag[5],num;
bool check(Node a,int k)
{
if(a.x<0||a.x>=n||a.y<0||a.y>=m) return false;
if(ma[k][a.x][a.y]=='X'||ma[k][a.x][a.y]=='O') return false;
return true;
}
void bfs(Node a,int k)
{
Node now,next;
queue<Node>que;
que.push(a);
vis[k][a.x][a.y]=1;
while(!que.empty())
{
now=que.front();
que.pop();
for(int i=0; i<4; i++)
{
next.x=now.x+dir[i][0];
next.y=now.y+dir[i][1];
if(!check(next,k)||vis[k][next.x][next.y]) continue;
if(ma[k][next.x][next.y]=='C')
{
ans++;
last_ans=max(ans,last_ans);
ma[k][next.x][next.y]='.';
}
vis[k][next.x][next.y]=1;
que.push(next);
}
}
}
void dfs(int k)
{
for(int i=0; i<cnt; i++)
{
if(flag[i]) continue;
for(int j=0; j<4; j++)
{
int tx=stone[i].x+dir[j][0];
int ty=stone[i].y+dir[j][1];
if(tx<0||tx>=n||ty<0||ty>=m||ma[k-1][tx][ty]!='.') continue;
int ttx=stone[i].x-dir[j][0];
int tty=stone[i].y-dir[j][1];
if(ttx<0||ttx>=n||tty<0||tty>=m||!vis[k-1][ttx][tty]) continue;
memcpy(vis[k],vis[k-1],sizeof(vis[k]));
memcpy(ma[k],ma[k-1],sizeof(ma[k]));
ma[k][tx][ty]='X',ma[k][stone[i].x][stone[i].y]='.';
flag[i]=1;
bfs(stone[i],k);
if(last_ans==num) return;
dfs(k+1);
if(last_ans==num) return;
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
if(ma[k-1][i][j]=='C'&&ma[k][i][j]=='.')
ans--;
flag[i]=0;
}
}
}
int main()
{
int T;
Node a;
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&m);
for(int i=0; i<n; i++)
scanf("%s",ma[0][i]);
cnt=num=0;
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
{
if(ma[0][i][j]=='S')
{
a.x=i,a.y=j;
ma[0][i][j]='.';
}
else if(ma[0][i][j]=='O')
stone[cnt].x=i,stone[cnt++].y=j;
else if(ma[0][i][j]=='C')
num++;
}
ans=last_ans=0;
memset(vis[0],0,sizeof(vis[0]));
memset(flag,0,sizeof(flag));
bfs(a,0);
dfs(1);
printf("%d\n",last_ans);
}
return 0;
}
病毒
Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 930 Solved: 395
[ Submit][ Status][ Web Board]
Description
Input
Output
对于每组数据,输出真实事件序列的最长可能长度。
Sample Input
1
9 1 4 2 6 3 8 5 9 1
6 2 7 6 3 5 1
Sample Output
3
思路:裸的LCIS,做LCS的时候维护上升即可
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
#define N 1050
int a[N],b[N];
int dp[N];
int n,m;
int LICS()
{
int i,j,MAX;
memset(dp,0,sizeof(dp));
for(i = 1; i<=n; i++)
{
MAX = 0;
for(j = 1; j<=m; j++)
{
if(a[i]>b[j] && MAX<dp[j])
MAX = dp[j];
if(a[i]==b[j])
dp[j] = MAX+1;
}
}
MAX = 0;
for(i = 1; i<=m; i++)
if(MAX<dp[i])
MAX = dp[i];
return MAX;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
scanf("%d",&m);
for(int i=1;i<=m;i++)
scanf("%d",&b[i]);
printf("%d\n",LICS());
}
return 0;
}