2022-XTU程设练习3
两个题没写,被恶心到了,也许也是我太菜了,如果有疑问或者纠错,或者想告诉我某些我不会的题的思路。可以评论区发给我,我很乐意的,。。。另外我程设居然过了,感谢谢大手下留情......
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: No1: 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 33 2 1 2 1 37 6 1 3 2 3 3 4 4 5 5 6 5 75 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++){//Floydfor(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-1printf("%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;
}
2022-XTU程设练习3相关推荐
- E:魔兽世界三(开战) 2022春季程设实习
描述 魔兽世界的西面是红魔军的司令部,东面是蓝魔军的司令部.两个司令部之间是依次排列的若干城市,城市从西向东依次编号为1,2,3 - N ( N <= 20).红魔军的司令部算作编号为0的城市, ...
- 航空航天大类C语言程设第三次练习赛
航空航天大类C语言程设第三次练习赛 第四期更新, 鸽子博主终于更新第三次练习赛了 (A题)求区间交并集 多行数据,每行有两个数,用空格分开,表示每个区间的下和上界,保证是合法的非空集,而且得到的并集是 ...
- BUAA程设第四周上机总结
BUAA程设第四周上机总结 代码格式化 基本输入输出 输入 scanf的小技巧 注意事项 关于字符串读入 输出 printf格式控制符的操作 标识变量的使用 代码格式化 同学们的码风可能一时半会不好培 ...
- BUAA程设第五周总结
BUAA程设第五周总结 自定义函数的注意事项 不要和已有的函数重名 函数只能返回一个值 注意使用函数过程中发生的隐式类型转换 使用各种方法替代define 使用const全局变量 使用typedef ...
- 让技术被看见——2022携程技术极客文化节
提到携程技术,你会想到什么? 提到携程技术人呢,你又会想到什么? 很多时候,技术扮演着业务发展背后的支撑和引擎的角色:同样,技术人,也往往隐藏在一行行代码背后,来和用户沟通和交流. 今天,借着1024 ...
- 程设刷题 | 程序设计实践II-2017(部分)
目录 1165-算术题 题目描述 代码实现 1184-Tourist 1 题目描述 代码实现 1186-Tourist 2 题目描述 代码实现 1224-LOVE 题目描述 代码实现 1256-湘潭大 ...
- 北大程设 魔兽终极版总结
几个坑: 1.已经走到对方基地但是此时还没有赢的武士,仍需要报告工作 2.dragon的yell条件是自己没有死(对方是被弓射死会yell) 3.在有敌人的城市被射死会影响旗帜更换 4.奖励,获得生命 ...
- C++程设实验项目三:黑白棋与基于UCT算法的AI
在这篇博客里,我将总结一下在这次实验中学到的UCT算法实现原理. 首先是参考文章: https://blog.csdn.net/u014397729/article/details/27366363 ...
- CVPR 2022 | 南开程明明团队和天大提出LD:目标检测的定位蒸馏
作者:Jin.Carlo | 已授权转载(源:知乎)编辑:CVer https://zhuanlan.zhihu.com/p/474955539 先上我们文章和代码: Localization D ...
最新文章
- 为什么尽量避免使用 CSS 表达式
- 优质的网站结构设计有哪些好处?
- 图像中添加二项式分布噪声
- 简单几步教你去除开机出现扫描硬盘!
- kotlin学习笔记——集合及集合操作符
- ubuntu安装 ftpd server(vsftpd)
- DrawTool画笔之图形笔
- JVM 垃圾回收算法机制及其实现原理
- Redis简介、安装、配置、启用学习笔记
- Error parsing YAML config file: yaml-cpp: error at line
- 大数据导论章节答案_智慧树APP大数据导论第三单元章节测试答案
- python课设参考文献_Python课程设计任务书
- python 柱状图和折线图放在一起_python中用matplotlib画折线图、柱状图、散点图
- 刷屏专用超长复制_求超长的刷屏文字
- HTML——使用表格制作个人简历
- DLNA使用设置教程
- 百度-还可以这样玩!
- python编辑svg文件_使用Python创建SVG
- “搜索大战”正式打响,微软发布ChatGPT版搜索引擎和浏览器
- 水果店促销方案,水果店开业怎么搞促销
热门文章
- RISC-V共建 | openKylin与深度数智战略合作会议召开
- 随便写写,都是我从网上收集的东西!
- OpenGL粒子系统和变换反馈
- winaip文档服务器打印,使用 Win32 API 将原始数据发送到打印机
- 网页制作工具哪款软件最好?
- (一)物联网云平台--阿里云--创建属于自己的产品和设备
- 压铸模具计算机台吨位公式,如何根据产品计算压铸机吨位
- 黑叔推荐:6个上班摸鱼的网址!
- 学计算机pr学的好有用吗,别人用手机剪映剪辑出来的视频,比我用电脑pr剪辑的还要好?瞬间被打击了,我学习了pr还有什么优势吗?_科技数码通...
- 系统文件夹合并在一起怎么办?