两个题没写,被恶心到了,也许也是我太菜了,如果有疑问或者纠错,或者想告诉我某些我不会的题的思路。可以评论区发给我,我很乐意的,。。。另外我程设居然过了,感谢谢大手下留情......
1.逆序数(大数据)-1167
样例输入
3 3 1 2 4 1 2 3 4 0
样例输出
2 0
思路:只能归并排序和树状数组,这里我讲讲归并排序。
很好理解,只是自己还是不会敲出来,就是从中间开始分,同时排序左右两边,在左边基础上又分为左右两边,在右边的基础上又分为左右两边,将大的排序分为小的排序,排序完成然后全部整合。
在排序的过程中你会发现,左边还没来得及复制的T就是所以比a[j]大的数,所以加m-q即可。
Memory: 1516K | Time: 234MS |
#include <stdio.h>
#include <string.h>
using namespace std;
int a[10001];
int temp[10001];//中介,这个是排序后的结果
int res=0;
void MergeSort(int x,int y)
{
if(y-x>1){
int sum=0;
int m=(x+y)/2;
int p=x,q=m,i=x;
MergeSort(x,m);
MergeSort(m,y);
while(p<m||q<y){
if(q>=y||(p<m&&a[p]<=a[q])){
temp[i++]=a[p++];
}
else{
temp[i++]=a[q++];
sum+=m-p;//x_______m_______y,p在x-m之间,q在m-y之间
}
}
for(int i=x;i<y;i++){
a[i]=temp[i];
}
res+=sum;
}
}
int main()
{
int n;
scanf("%d",&n);
while(n!=0){
res=0;
memset(a,0,sizeof(a));
memset(temp,0,sizeof(temp));
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
MergeSort(0,n);
/*for(int i=0;i<n;i++){
printf("%d ",a[i]);
}*/
printf("%d\n",res);
scanf("%d",&n);
}
return 0;
}
2.1179-Shortest Path
样例输入
3 3 1 1 2 3 2 3 4 1 3 2 2 0 0 0
样例输出
7
思路:dijkstra算法。但是注意啊,有重边取最小,而且必须按顺序经过且只能经过一次,所以一开始就得有路径被标记成已经走过,举个栗子。
1----a1----a2----a3----n
从1开始必须终点是a1,所以,a2,a3,n它不能走。
a1的终点是a2,因此1,a3,n它不能走。
a2,1,a1,n不能走。
......
所以开始就标记已经走过即可。
Memory: 6120K | Time: 1999MS |
#include <stdio.h>
#include <queue>
#include <algorithm>
#include <string.h>
#include <limits.h>
typedef long long ll;
using namespace std;
int d[1101];
int vis[1101];
int s[1101][1101];
int n,m,k;
struct node
{
int x,y;
bool operator<(const node&b)const
{
return y>b.y;
}
};
void djsrt(int t)
{
fill(d,d+1101,INT_MAX/2);
d[t]=0;
priority_queue<node>q;
node temp;
temp.x=t,temp.y=0;
q.push(temp);
while(!q.empty()){
node st=q.top();
q.pop();
if(vis[st.x]==1){
continue;
}
vis[st.x]=1;
int a=st.x;
for(int i=0;i<n;i++){
if(vis[i]==0&&s[a][i]<INT_MAX/2){
if(d[i]>d[a]+s[a][i]){
d[i]=d[a]+s[a][i];
q.push((node){i,d[i]});
}
}
}
}
}
int main()
{
//FILE *fpRead=fopen("D://huancun//1179//std.in","r");
scanf("%d%d%d",&n,&m,&k);
while(1){
if(n==m&&m==k&&k==0){
break;
}
int a[3];
memset(a,0,sizeof(a));
fill(s[0],s[0]+1101*1101,INT_MAX/2);
for(int i=0;i<m;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(s[a-1][b-1]>c){
s[a-1][b-1]=c;
s[b-1][a-1]=c;
}
}
for(int i=0;i<k;i++){
scanf("%d",&a[i]);
}
ll res=0;
memset(vis,0,sizeof(vis));
if(k==0){//暴力一点,看得更清楚
djsrt(0);
res+=d[n-1];
}
else if(k==1){
vis[n-1]=1;//标记
djsrt(0);
res+=d[a[0]-1];
memset(vis,0,sizeof(vis));
vis[0]=1;
djsrt(a[0]-1);
res+=d[n-1];
}
else if(k==2){
vis[n-1]=1;//标记
vis[a[1]-1]=1;
djsrt(0);
res+=d[a[0]-1];
memset(vis,0,sizeof(vis));
vis[n-1]=1;
vis[0]=1;
djsrt(a[0]-1);
res+=d[a[1]-1];
memset(vis,0,sizeof(vis));
vis[0]=1;
vis[a[0]-1]=1;
djsrt(a[1]-1);
res+=d[n-1];
}
else if(k==3){
vis[n-1]=1;//标记
vis[a[1]-1]=1;
vis[a[2]-1]=1;
djsrt(0);
res+=d[a[0]-1];
memset(vis,0,sizeof(vis));
vis[n-1]=1;
vis[0]=1;
vis[a[2]-1]=1;
djsrt(a[0]-1);
res+=d[a[1]-1];
memset(vis,0,sizeof(vis));
vis[n-1]=1;
vis[0]=1;
vis[a[0]-1]=1;
djsrt(a[1]-1);
res+=d[a[2]-1];
memset(vis,0,sizeof(vis));
vis[0]=1;
vis[a[0]-1]=1;
vis[a[1]-1]=1;
djsrt(a[2]-1);
res+=d[n-1];
}
if(res>=INT_MAX/2){
printf("Impossible\n");
}
else{
printf("%lld\n",res);
}
scanf("%d%d%d",&n,&m,&k);
}
return 0;
}
3.1195-Large Population
Sample Input | ||
2 2 1 1 2 1 3 3 1 2 1 1 3 2 2 3 3 | ||
Sample Output | ||
1 5 |
思路:prim()算法,要求最大,我们只需要反过来把输入变成负数,因为prim求的是最小,这样求出来之后然后取反即可。注意重边,当时long好像不能用,所以只能用I64。
Memory: 9224K | Time: 1343MS |
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <limits.h>
using namespace std;
typedef long long ll;
__int64 matx[1011][1011];
__int64 visited[1011];
__int64 d[1011];
int n,m;
__int64 prim()
{
fill(d,d+1010,INT_MAX);
d[0]=0;
__int64 res=0;
for(int i=0;i<n;i++){
__int64 mins=INT_MAX,id=0;
for(int j=0;j<n;j++){
if(visited[j]==0&&d[j]<mins){
id=j;
mins=d[j];
}
}
//printf("%d ",id);
visited[id]=1;
res+=d[id];
//printf("%lld\n",res);
for(int k=0;k<n;k++){
if(visited[k]==0&&matx[id][k]!=INT_MAX&&matx[id][k]<d[k]){
d[k]=matx[id][k];
}
}
}
return res;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
memset(visited,0,sizeof(visited));
fill(matx[0],matx[0]+1010*1010,INT_MAX);
for(int i=0;i<m;i++){
int a,b;
__int64 c;
scanf("%d%d%I64d",&a,&b,&c);
if(matx[a-1][b-1]>-c){
matx[a-1][b-1]=-c;
matx[b-1][a-1]=-c;
}
}
__int64 res=prim();
printf("%I64d\n",-res);
}
return 0;
}
4.1245-Lisa's Puzzle
样例输入
5 5 13 1 2 3
样例输出
1 0 3 0 0
思路:这个题目很有意思,我们可以把它当做一个字典树,因为是二进制,所以是二叉字典树,树的每一个节点都可以表示一个数,这样后缀就可以直观看到了。
Memory: 26352K | Time: 968MS |
#include <stdio.h>
#include <unordered_map>
using namespace std;
typedef long long ll;
ll b[100010]={0};
int main()
{
unordered_map<ll,ll>a;
int n;
scanf("%d",&n);
int t=0;
while(n--){
ll m;
scanf("%lld",&m);
b[t++]=m;
ll ans=0;
while(m!=0){
if(m%2==1){
ans=ans*2+2;
a[ans]++;
}
else{
ans=ans*2+1;
a[ans]++;
}
m/=2;
}
}
for(ll i=0;i<t;i++){
ll ans=0;
ll res=INT_MAX;
while(b[i]!=0){
if(b[i]%2==1){
ans=ans*2+2;
res=min(res,a[ans]);
}
else{
ans=ans*2+1;
res=min(res,a[ans]);
}
b[i]/=2;
}
printf("%lld\n",res-1);
}
return 0;
}
5.1250-Bonus
样例输入
2 3 2 1 2 2 3 3 2 1 2 2 1
样例输出
5664 2888 1888 888 2664 888 888 888
思路:拓扑和bfs选一个即可,只是题意感觉不怎么明白。参考了别人的题解。
Memory: 4200K | Time: 452MS |
#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;
typedef long long ll;
vector<ll>res[10010];
ll s[10010],vis[10010];
ll dfs(ll nums)
{
vis[nums]=-1;//正在访问
for(ll i=0;i<res[nums].size();++i){
ll id=res[nums][i];
if(vis[id]<0){
return -1;
}
if(vis[id]==0){
s[id]=dfs(id);
}
if(s[id]<0){
return -1;
}
if(s[nums]<s[id]+1000){
s[nums]=s[id]+1000;
}
}
vis[nums]=1;
return s[nums];
}
ll ts(ll n)
{
memset(vis,0,sizeof(vis));
for(ll i=1;i<=n;i++){
if(!vis[i]&&dfs(i)<0){
return -1;
}
}
return 0;
}
int main()
{
ll t;
scanf("%lld",&t);
while(t--){
ll n,m;
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=n;i++){
res[i].clear();
s[i]=888;
}
for(ll i=0;i<m;i++){
ll a,b;
scanf("%lld%lld",&a,&b);
res[a].push_back(b);
}
ll sum=0;
if(ts(n)<0){
sum=n*888;
printf("%lld\n",sum);
for(ll i=1;i<n;i++){
printf("%lld ",888);
}
printf("888\n");
}
else{
for(ll i=1;i<=n;i++){
sum+=s[i];
}
printf("%lld\n",sum);
for(ll i=1;i<n;i++){
printf("%lld ",s[i]);
}
printf("%lld\n",s[n]);
}
}
return 0;
}
6.1288-Binary Search Tree
样例输入
2 5 5 3 2 5 1 4 3 1 2 5 4 3 2 1 5 4 3 5 2 1 4 3 5 4 2 1 3 2 4 5 1 3 2 1 2 3 1 3 2 3 2 1
样例输出
1: No 2: Yes 3: Yes 4: Yes 5: No 1: No 2: No
思路:中+前/后序遍历绝对一棵树 ,所以最直观的方法就是前序或者后续遍历即可,还能优化一下,但是能过已经够了。
Memory: 63808K | Time: 1734MS |
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
int ch[1001],flag=0,ans=0;
struct Treenode
{
int val;
Treenode *l;
Treenode *r;
};
Treenode* create(Treenode* t)//二叉树模板
{
t=new Treenode;
t->l=nullptr;
t->r=nullptr;
return t;
}
Treenode* into(Treenode* t,int val)
{
if(t==nullptr){
t=create(t);
t->val=val;
return t;
}
if(val<t->val){
t->l=into(t->l,val);
return t;
}
if(val>t->val){
t->r=into(t->r,val);
return t;
}
}
void pre(Treenode* t)//前序
{
if(t==nullptr){
return;
}
ch[ans++]=t->val;
pre(t->l);
pre(t->r);
}
void pres(Treenode* t)//前序
{
if(t==nullptr){
return;
}
if(ch[ans++]!=t->val){
flag=1;
return;
}
pres(t->l);
pres(t->r);
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
int n,m;
flag=0,ans=0;
scanf("%d%d",&n,&m);
memset(ch,0,sizeof(ch));
Treenode *root=nullptr;
for(int i=0;i<n;i++){
int nums;
scanf("%d",&nums);
root=into(root,nums);
}
pre(root);
for(int i=0;i<m;i++){
flag=0;
ans=0;
Treenode *t=nullptr;
for(int j=0;j<n;j++){
int nums;
scanf("%d",&nums);
t=into(t,nums);
}
pres(t);
if(flag==0){
printf("%d: Yes\n",i+1);
}
else{
printf("%d: No\n",i+1);
}
}
printf("\n");
free(root);
}
return 0;
}
7.1302-Balance Tree
样例输入
3 5 4 3 2 1 5 5 3 4 2 1 5 5 4 2 1 3 5
样例输出
No Yes Yes
思路:跟上题目是同一个类型的,我们只需要学会找二叉树深度,这个题目就挺简单了。
Memory: 4708K | Time: 125MS |
#include <stdio.h>
#include <algorithm>
using namespace std;
struct Treenode
{
int val;
Treenode *l;
Treenode *r;
};
int flag=0;
Treenode* create(Treenode* t)//二叉树模板
{
t=new Treenode;
t->l=nullptr;
t->r=nullptr;
return t;
}
Treenode* into(Treenode* t,int val)
{
if(t==nullptr){
t=create(t);
t->val=val;
return t;
}
if(val<t->val){
t->l=into(t->l,val);
return t;
}
if(val>t->val){
t->r=into(t->r,val);
return t;
}
}
int dfs(Treenode *t)//求深度
{
if(t==nullptr){
return 0;
}
int left=dfs(t->l);
int right=dfs(t->r);
if(abs(left-right)>1){//左子树和右子树深度
flag=1;
return max(left,right)+1;
}
return max(left,right)+1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
flag=0;
int n;
scanf("%d",&n);
Treenode *root=nullptr;
for(int i=0;i<n;i++){
int nums;
scanf("%d",&nums);
root=into(root,nums);
}
dfs(root);
if(flag==0){
printf("Yes\n");
}
else{
printf("No\n");
}
}
return 0;
}
8.1369-Black White Chess
样例输入
5 0000000000000000 1111111111111111 0000111100001111 1000000000000000 1100000000000011
样例输出
0 0 2 -1 4
思路:一遍bfs即可,找到所有的可能,计算最小。
Memory: 7652K | Time: 514MS |
#include <iostream>
#include <queue>
#include <unordered_map>
typedef long long ll;
using namespace std;
unordered_map<string,ll>hashmap;
int a[10001];
string cows(string s,int n)//行
{
for(int i=n*4;i<n*4+4;i++){
if(s[i]=='0'){
s[i]='1';
}
else{
s[i]='0';
}
}
return s;
}
string rows(string s,int n)//列
{
for(int i=n;i<n+16;i+=4){
if(s[i]=='0'){
s[i]='1';
}
else{
s[i]='0';
}
}
return s;
}
string mids(string s,int n)//四个
{
for(int i=n;i<n+2;i++){
if(s[i]=='0'){
s[i]='1';
}
else{
s[i]='0';
}
}
for(int i=n+4;i<n+6;i++){
if(s[i]=='0'){
s[i]='1';
}
else{
s[i]='0';
}
}
return s;
}
void bfs()//bfs
{
string s;
pair<string,ll>res;
queue<pair<string,ll>>p;
int ans=1;
for(int i=0;i<16;i++){//初始化两个原状态
s+='0';
}
res.first=s;
res.second=0;
p.push(res);
for(int i=0;i<16;i++){
s[i]='1';
}
res.first=s;
res.second=0;
p.push(res);
while(!p.empty()){
string sp=p.front().first;
int x=p.front().second;
p.pop();
if(hashmap[sp]!=0){//maps储存是否已经出现
continue;
}
else{
hashmap[sp]=ans++;
}
a[hashmap[sp]]=x;//x是最小次数
//cout<<sp<<" "<<x<<endl;
for(int i=0;i<4;i++){
p.push({cows(sp,i),x+1});
}
for(int i=0;i<4;i++){
p.push({rows(sp,i),x+1});
}
for(int i=0;i<3;i++){
p.push({mids(sp,i),x+1});
}
for(int i=4;i<7;i++){
p.push({mids(sp,i),x+1});
}
for(int i=8;i<11;i++){
p.push({mids(sp,i),x+1});
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
bfs();
while(t--){
string m;
cin>>m;
if(hashmap[m]==0){
cout<<-1<<endl;
}
else{
cout<<a[hashmap[m]]<<endl;
}
}
return 0;
}
9.1370-Ball
样例输入
4 3 2 1 2 2 3 3 2 1 2 1 3 7 6 1 3 2 3 3 4 4 5 5 6 5 7 5 6 1 2 1 3 1 4 1 5 2 3 2 4
样例输出
2 0 4 0
思路:当时我是真的没有想到用Floyd算法,我们先把每个边根据Floyd初始化,然后使用一次Floyd,然后看每个点与其他的点的距离是否是无限大,如果是无限大那么说明出度或者入度就0,否则入度或者出度+1,最后再比较入度和出度是否都是一半。
Memory: 1248K | Time: 77MS |
#include <stdio.h>
#include <string.h>
#include <limits.h>
using namespace std;
int d[101][101];
int main()
{
int t;
scanf("%d",&t);
while(t--){
int n,m;
scanf("%d%d",&n,&m);
memset(d,0,sizeof(d));
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){//Floyd初始化
if(i==j){
d[i][j]=0;
}
else{
d[i][j]=INT_MAX/2;
}
}
}
for(int i=0;i<m;i++){
int a,b;
scanf("%d%d",&a,&b);
d[a-1][b-1]=1;
}
for(int i=0;i<n;i++){//Floyd
for(int j=0;j<n;j++){
for(int k=0;k<n;k++){
if(d[j][k]>d[j][i]+d[i][k]){
d[j][k]=d[j][i]+d[i][k];
}
}
}
}
//cout<<d[0][1]<<endl;
//cout<<INT_MAX/2;
int flag=0;
for(int i=0;i<n;i++){
int a=0;
for(int j=0;j<n;j++){
if(d[i][j]!=0&&d[i][j]!=INT_MAX/2){//如果不是无限大,说明有出度或者入度
if(d[i][j]>0){
/*if(i==1)
cout<<i<<" "<<j<<" "<<d[i][j]<<endl;*/
a++;
}
}
}
if(a==(n-1)/2){//如果入度或者出度中的一个等于中间,那么继续寻找出度或者入度
a=0;
for(int k=0;k<n;k++){
if(d[k][i]!=0&&d[k][i]!=INT_MAX/2){
a++;
}
}
if(a==(n-1)/2){//两个都是的话说明是中间的了
flag=1;
printf("%d\n",i+1);
}
}
}
if(flag==0){
printf("%d\n",0);
}
}
return 0;
}
10.1378-Blocks
以前的博客有,可以去翻我以前的题解。
11.1387-打字机
不想写wwww
12.1389-二叉查找树
样例输入
2 5 3 2 1 4 5 5 4 5 3 2 1
样例输出
1 2
思路:模板题,没什么说的。
Memory: 14952K | Time: 546MS |
#include <stdio.h>
#include <algorithm>
using namespace std;
struct Treenode
{
int val;
Treenode *l;
Treenode *r;
};
int mins=0;
Treenode* create(Treenode* t)
{
t=new Treenode;
t->l=nullptr;
t->r=nullptr;
return t;
}
Treenode* into(Treenode* t,int val)
{
if(t==nullptr){
t=create(t);
t->val=val;
return t;
}
if(val<t->val){
t->l=into(t->l,val);
return t;
}
if(val>t->val){
t->r=into(t->r,val);
return t;
}
}
int dfs(Treenode *t)
{
if(t==nullptr){
return 0;
}
int left=dfs(t->l);
int right=dfs(t->r);
mins=max(abs(left-right),mins);
return max(left,right)+1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
mins=0;
int n;
scanf("%d",&n);
Treenode *root=nullptr;
for(int i=0;i<n;i++){
int nums;
scanf("%d",&nums);
root=into(root,nums);
}
dfs(root);
printf("%d\n",mins);
}
return 0;
}
13.1398-积木II
样例输入
2 6 3 9 3
样例输出
2 6
思路:其实跟积木I没什么区别,我们想一想,积木经过全排列后,我们只需要从中拿出一段排好序列放到后面,就是这个题目的意思了,那么拿出的方式有
是不是很神奇?那你就大错特错了,其实题解上这个公式思路是对的,但是运算并不是这个,其实实际的m应该是m-1,因为你排好序后最后最大的那一位是不能动的。
Memory: 1732K | Time: 312MS |
#include <stdio.h>
#include <string.h>
#include <math.h>
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--){
int n,m;
int dp[110][11][110];
memset(dp,0,sizeof(dp));
dp[1][1][1]=1;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
for(int k=1;k<=i;k++){
if(j==1){
if(i==k)dp[i][j][k]=1;
else dp[i][j][k]=0;
}
else{
for(int s=k-1;s>=1;s--){
dp[i][j][k]+=dp[i-k][j-1][s];
}
}
}
}
}
int res=0;
for(int i=1;i<=n;i++){
res+=dp[n][m][i];
}
res*=pow(2,m-1)-2;//最终结果应该是m-1
printf("%d\n",res);
}
return 0;
}
14.1409-Splite
样例输入
2 5 2 1 2 3 4 5 5 3 1 5 2 4 3
样例输出
17 15
思路:典型的dp题,一定要注意初始化啊!!!!
Memory: 1480K | Time: 0MS |
#include <stdio.h>
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--){
int a[51];
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int dp[55][55];
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++){
dp[i][1]=abs(a[i]-a[1])*i;
}
dp[1][1]=a[1];
for(int i=1;i<=n;i++){
for(int k=1;k<=m;k++){
if(k==1){
continue;
}
for(int j=i-1;j>=0;j--){
if(k-1>j){
dp[i][k]=max(dp[i][k],dp[i-1][k-1]+a[i]);
continue;
}
dp[i][k]=max(dp[i][k],max(dp[i-1][k-1]+a[i],dp[j][k-1]+(i-j)*abs(a[j+1]-a[i])));
}
}
}
printf("%d\n",dp[n][m]);
}
return 0;
}
15.1410-Anniversary
样例输入
1 4 7 2 1 2 7 1 3 2 2 3 1 3 2 2 3 4 5 2 1 3 4 2 3
样例输出
9
思路:构造一个正图,一个反图,分别使用dijkstra算法。
Memory: 9228K | Time: 1375MS |
#include <stdio.h>
#include <queue>
#include <string.h>
#include <algorithm>
#include <limits.h>
using namespace std;
int s[1001][1001];
int s2[1001][1001];
int d[1001];
int vis[1001], n, m, e;
int p[1001],g[1001];
struct node
{
int a, b;
bool operator<(const node&c)const
{
return b > c.b;
}
};
void djstr(int st)
{
fill(d, d + 1001, INT_MAX/2);
d[st] = 0;
priority_queue<node>q;
node t;
t.a = st, t.b = 0;
q.push(t);
memset(vis, 0, sizeof(vis));
while (!q.empty()) {
node x = q.top();
q.pop();
int a = x.a;
if (vis[a] == 1) {
continue;
}
vis[a] = 1;
for (int i = 0;i < n;i++) {
if (!vis[i] && s[a][i] < INT_MAX/2) {
if (d[i] > d[a] + s[a][i]) {
d[i] = d[a] + s[a][i];
node temp;
temp.a = i;
temp.b = d[i];
q.push(temp);
}
}
}
}
}
void djstr1(int st)
{
fill(d, d + 1001, INT_MAX / 2);
d[st] = 0;
priority_queue<node>q;
node t;
t.a = st, t.b = 0;
q.push(t);
memset(vis, 0, sizeof(vis));
while (!q.empty()) {
node x = q.top();
q.pop();
int a = x.a;
if (vis[a] == 1) {
continue;
}
vis[a] = 1;
for (int i = 0;i < n;i++) {
if (!vis[i] && s2[a][i] < INT_MAX / 2) {
if (d[i] > d[a] + s2[a][i]) {
d[i] = d[a] + s2[a][i];
//printf("%d ", d[i]);
node temp;
temp.a = i;
temp.b = d[i];
q.push(temp);
}
}
}
}
}
int main()
{
int t;
scanf("%d", &t);
while (t--) {
memset(p, 0, sizeof(p));
memset(g, 0, sizeof(g));
fill(s[0], s[0] + 1001 * 1001, INT_MAX/2);
fill(s2[0], s2[0] + 1001 * 1001, INT_MAX / 2);
scanf("%d%d%d", &n, &m, &e);
for (int i = 0;i < m;i++) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
if (s[x - 1][y - 1] > z) {
s[x - 1][y - 1] = z;
s2[y - 1][x - 1] = z;
}
}
djstr(e - 1);
for(int i = 0;i < n;i++) {
g[i] = d[i];//e到各个节点
}
djstr1(e - 1);
for (int i = 0;i < n;i++) {
p[i] = d[i];
}
int res = -1;
for (int i = 0;i < n;i++) {
if (i == e - 1) continue;
int ans = p[i] + g[i];
//printf("%d\n", ans);
res = max(res, ans);
}
printf("%d\n", res);
}
return 0;
}
16.消星星-1418
输出
对于每个样例,每行输出一个答案,表示消灭所有星星至少需要多少能量。
样例输入
2 2 2 ab ba 3 3 aab cab ccb
样例输出
4 3
思路:dfs即可,遍历完直接就可以退出。
Memory: 2188K | Time: 125MS |
#include <stdio.h>
#include <string.h>
using namespace std;
char s[1001][1001];
int nums=0,n,m;
void dfs(int x,int y,char a)
{
if(x>=n||x<0||y>=m||y<0||s[x][y]==0||s[x][y]!=a){
return;
}
s[x][y]=0;
nums++;
dfs(x+1,y,a);
dfs(x-1,y,a);
dfs(x,y+1,a);
dfs(x,y-1,a);
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
memset(s,0,sizeof(s));
nums=0;
int res=0;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
scanf("%s",s[i]);
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(s[i][j]==0){
continue;
}
if(nums==n*m){
break;
}
dfs(i,j,s[i][j]);
res++;
}
if(nums==n*m){//遍历全部即可退出
break;
}
}
printf("%d\n",res);
}
return 0;
}
17.1428-Train
样例输入
2 3 10 10 6 4 9 2 7 4 8 3 6 3 10 10 11 1 1 2 12 2 13 13 3
样例输出
10 0
思路:典型的背包dp问题,如果不明白的可以去搜索01背包 问题。
Memory: 1616K | Time: 139MS |
#include <iostream>
#include <string.h>
using namespace std;
typedef long long ll;
struct node
{
ll v,x,w;
}res[1001];
ll dp[101][101];
int main()
{
ll t;
cin>>t;
while(t--){
ll n,m,s;
cin>>n>>m>>s;
for(ll i=1;i<=n;i++){
cin>>res[i].v>>res[i].x>>res[i].w;
}
memset(dp,0,sizeof(dp));
for(ll i=1;i<=n;i++){
for(ll j=m;j>=res[i].v;j--){ //转移方程,要么装,要么不装,只有两种选择
for(ll k=s;k>=res[i].x;k--){//不装那就是前一个状态,装就是前一个状态+现在状态
if(j>=res[i].v&&k>=res[i].x){
dp[j][k]=max(dp[j][k],dp[j-res[i].v][k-res[i].x]+res[i].w);
}
else{
dp[j][k]=dp[j][k];
}
}
}
}
cout<<dp[m][s]<<endl;
}
return 0;
}
18.1433-Swap Digits 不会......
19.1434-Lost Digits
样例输入
2 7? ?7
样例输出
2 1
思路:dp题,转移方程看我代码,这里不好敲。
Memory: 1532K | Time: 15MS |
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--){
int dp[20][8];
memset(dp,0,sizeof(dp));
string s;
cin>>s;
int n=s.size();
if(n==1&&s[0]=='?'){
cout<<2<<endl;
continue;
}
if(s[0]!='?'){
dp[0][(s[0]-'0')%7]=1;
}
else{
for(int i=0;i<10;i++){
dp[0][i%7]++;
}
dp[0][0]--;
}
for(int i=1;i<=n;i++){
if(s[i]=='?'){//如果是问号,那么对0-9都得做贡献
for(int k=0;k<10;k++){
for(int j=0;j<7;j++){
dp[i][(10*j+k)%7]+=dp[i-1][j];//状态转移方程
}
}
}
else{
for(int j=0;j<7;j++){//否则只对指定做贡献
dp[i][(10*j+(s[i]-'0'))%7]+=dp[i-1][j];
}
}
}
cout<<dp[n-1][0]<<endl;
}
return 0;
}
20.1435-Path
样例输入
2 3 2 1 1 2 1 2 3 2 2 3 2 2 1 2 1 2 3 2 1 3
样例输出
3 1
思路:还是dijkstra算法,只不过要用超级原点,什么是超级原点呢?就是一个虚拟的点,要求他对所有起点的距离都是0,那么这样的话求出的距离不就是所有起点到终点的距离么?然后dijkstra算法就能求出最短的距离,也是很不错了。
Memory: 5372K | Time: 874MS |
#include <stdio.h>
#include <limits.h>
#include <algorithm>
#include <queue>
#include <string.h>
using namespace std;
typedef long long ll;
int s[1011][1011];
int d[1011];
int vis[1011];
int n,m,k;
struct node
{
int a, b;
bool operator<(const node&c)const
{
return b > c.b;
}
};
void djstr(int k)
{
fill(d, d + 1011, INT_MAX/2);
priority_queue<node>q;
while(k--){
int a;
scanf("%d",&a);
d[a]=0;
q.push((node){a,0});//所有点全部入栈,模拟超级原点,其他算法和dijkstra没有任何区别
}
memset(vis, 0, sizeof(vis));
while (!q.empty()) {
node x = q.top();
q.pop();
int a = x.a;
if (vis[a] == 1) {
continue;
}
vis[a] = 1;
for (int i = 1;i <= n;i++) {
if (!vis[i] && s[a][i] < INT_MAX/2) {
if (d[i] > d[a] + s[a][i]) {
d[i] = d[a] + s[a][i];
node temp;
temp.a = i;
temp.b = d[i];
q.push(temp);
}
}
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
fill(s[0],s[0]+1011*1011,INT_MAX/2);
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<m;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(s[a][b]>c){
s[a][b]=c;
s[b][a]=c;
}
}
djstr(k);
ll res=0;
for(int i=1;i<=n;i++){
res+=(ll)d[i];
}
if(res>=INT_MAX/2){
printf("-1\n");
continue;
}
printf("%lld\n",res);
}
return 0;
}