TOC【吴永辉】程序设计基础实践7-9I-L
I. The Balance
题意:求ax+by=c中|x|+|y|的最小值。
先解决ax+by=c对于x的最小正整数解,再解决对于y的最小正整数解,按照他的排序要求,找到最小的那个即可。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll exgcd(ll a,ll b,ll &x,ll &y){
ll d;
if(b){
d=exgcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
x=1;
y=0;
return a;
}
ll ab(ll x){
return x>0?x:-x;
}
ll w1,w2,c;
void work(){
ll d,anx,any,min1=2147483647,min2=2147483647,x,y;
d=exgcd(w1,w2,anx,any);
anx=anx*c/d;any=any*c/d;
x=anx;
y=any;
anx=(anx%(w2/d)+w2/d)%(w2/d);
any=any-(anx-x)/(w2/d)*(w1/d);
min1=ab(anx)+ab(any);
min2=anx*w1+any*w2;
x=anx;
y=any;
any=(any%(w1/d)+w1/d)%(w1/d);
anx=anx-(any-y)/(w1/d)*(w2/d);
if(min1>ab(anx)+ab(any)){
x=anx;y=any;
}
if(min1==ab(anx)+ab(any)){
if(min2>anx*w1+any*w2){
x=anx;
y=any;
}
}
cout<<ab(x)<<" "<<ab(y)<<endl;
}
int main()
{
while(scanf("%lld%lld%lld",&w1,&w2,&c)!=EOF){
if(w1==0&&w2==0&&c==0)break;
work();
}
return 0;
}
J. ID Codes
题意:找出字典序的下一个排列,如果一直是递减的,就输出“No Successor”。
1.用的是STL的模板
头文件:
函数名 next_permutation(参数)
作用:寻找当前序列的下一个排序(按字典序的顺序)
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s;
while(cin>>s&&s!="#"){
if(next_permutation(s.begin(),s.end()))
cout<<s<<endl;
else
cout<<"No Successor"<<endl;
}
return 0;
}
2.找下一个比他大的串,从后往前遍历,对当前i考虑i后的j,若a[i]<a[j],进行交换(a[j]取成立中最小的),并对i后的字符排序即可输出并退出循环。
#include<bits/stdc++.h>
using namespace std;
int cmp(const void*a,const void *b)
{
return *(int *)a-*(int *)b;
}
int main()
{
int i,j,m,n;
char a[110];
while(cin>>a&&a[0]!='#'){
int k=strlen(a);
char t;
for(i=k-2;i>=0;i--){
char min=a[i];
int flag=0;
for(j=i+1;j<k;j++){
if(a[j]>a[i]&&!flag){
min=a[j];flag=1;
}
else if(a[j]<min&&a[j]>a[i]&&flag) min=a[j];
}
if(min!=a[i]){
for(j=i+1;j<k;j++){
if(min==a[j]){
t=a[i];a[i]=a[j];a[j]=t;
for(m=i+1;m<k;m++){
for(n=m+1;n<k;n++){
if(a[m]>a[n]){
t=a[m];a[m]=a[n];a[n]=t;
}}}
puts(a);
break;
}
}
}
if(j<k) break;
}
if(i<0) cout<<"No Successor"<<endl;
}
return 0;
}
K. Schedule
题意:给n个任务的开始和结束时间,求最少用机器,和在这些机器上用的最少时间
#include<bits/stdc++.h>
using namespace std;
struct node{
int l,r;
bool operator <(const node a)const{
return l<a.l;
}
}seg[];
multiset<int>s;
multiset<int>::iterator it;
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
s.clear();
int n;
scanf("%d",&n);
for(int i=;i<n;i++)
{
scanf("%d %d",&seg[i].l,&seg[i].r);
}
int ans = ;//记录所用机器数量
long long res = ;//记录时间
sort(seg,seg+n);
for(int i=;i<n;i++)
{
it = s.upper_bound(seg[i].l);//寻找 >= seg[i].l 的r
if(it == s.begin())
{
ans++; //找不到 就重新开一个机器
res += seg[i].r - seg[i].l;
s.insert(seg[i].r);
continue;
}
it--;//这里就是离该i区间的起始点最近的 结束点
res += seg[i].r - *it;//把该i区间的结束点 接上上个结束点 这样就不用管 起始点在哪里了
s.erase(it);//把当前区间结束点删除
s.insert(seg[i].r);//重新更新
}
cout<<ans<<" "<<res<<endl;
}
}
L. Brackets Sequence
定义合法的括号序列如下:
1 空序列是一个合法的序列
2 如果S是合法的序列,则(S)和[S]也是合法的序列
3 如果A和B是合法的序列,则AB也是合法的序列
#include<bits/stdc++.h>
using namespace std;
const int N = 105;
const int SUP = 2e9;
int d[N][N], pos[N][N];
char s[N];
void match(int len)
{
for(int i = 0; i < len; i++)
d[i][i] = 1;//d值的含义:i和i+k之间应该添加的括号。起始条件:d[i][i] = 1;
for(int k = 1; k < len; k++)//枚举间隔
for(int i = 0; i + k < len; i++) {//枚举起点
d[i][i+k] = SUP;
if((s[i] == '(' && s[i+k] == ')') || (s[i] == '[' && s[i+k] == ']')) {//匹配
d[i][i+k] = d[i+1][i+k-1];
//情况一:左右交换:1。情况二:左右相等:1。情况三:内部需要几个它就需要几个
pos[i][i+k] = -1;
}
for(int tmp = i; tmp < i + k; tmp++)//枚举分界点
if(d[i][i+k] > d[i][tmp] + d[tmp+1][i+k]) {//DP
pos[i][i+k] = tmp;//该点处分开,解更优
d[i][i+k] = d[i][tmp] + d[tmp+1][i+k];//状态转移
}
}
}
void PR(int l, int r)
{
if(l > r) return;//递归边界
if(l == r) {
if(s[l] == '(' || s[l] == ')')
printf("()");
else
printf("[]");
}
else {
if(pos[l][r] == -1) {//匹配,则递归输出内部
putchar(s[l]);
PR(l+1, r-1);
putchar(s[r]);
}
else {//不匹配,则递归至最优分界点
PR(l, pos[l][r]);
PR(pos[l][r]+1, r);
}
}
}
int main()
{
scanf("%s", s);
int len = strlen(s);
match(len);
PR(0, len-1);//递归输出解
putchar('\n');
return 0;
}
571

被折叠的 条评论
为什么被折叠?



